- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在阅读了一些有关 java 内存模型和同步的内容后,出现了一些问题:
Even if Thread 1 synchronizes the writes, then although the effect of the writes will be flushed to main memory, Thread 2 will still not see them because the read came from level 1 cache. So synchronizing writes only prevents collisions on writes. (Java thread-safe write-only hashmap)
Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads. (https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html)
第三个网站(抱歉,我找不到了)说,对任何对象的每次更改(它不关心引用来自哪里)都会在方法离开同步块(synchronized block)并建立时刷新到内存中发生在之前的情况。
我的问题是:
退出同步块(synchronized block)真正刷新回内存的是什么? (有些网站也说只有获得锁的对象才会被刷新。)
在这种情况下,happens-before-relaitonship是什么意思?进入 block 时将从内存中重新读取什么,什么不是?
锁如何实现此功能(来自 https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Lock.html):
All Lock implementations must enforce the same memory synchronization semantics as provided by the built-in monitor lock, as described in section 17.4 of The Java™ Language Specification:
A successful lock operation has the same memory synchronization effects as a successful Lock action. A successful unlock operation has the same memory synchronization effects as a successful Unlock action. Unsuccessful locking and unlocking operations, and reentrant locking/unlocking operations, do not require any memory synchronization effects.
如果我关于所有内容都将被重新读取和刷新的假设是正确的,那么这是通过在锁定和解锁函数中使用同步块(synchronized block)来实现的(这也是大多数必要的),对吧?如果错了,这个功能如何实现?
提前谢谢您!
最佳答案
发生在关系之前是你必须理解的基本事情,如 the formal specification就按照这些来运作。 “冲洗”之类的术语是技术细节,可以帮助您理解它们,或者在最坏的情况下误导您。
如果线程执行操作 A
在synchronized(object1) { … }
内,后跟执行操作的线程 B
在synchronized(object1) { … }
内,假设object1
引用同一个对象,A
之间存在happens-before-relationship和B
并且这些操作对于访问共享可变数据是安全的(假设没有其他人修改此数据)。
但这是一个有向关系,即B
可以安全地访问A
修改的数据。但当看到两个synchronized(object1) { … }
block ,确保 object1
是同一个对象,你还需要知道是否A
在 B
之前执行或B
在 A
之前执行,了解发生在关系之前的方向。对于普通的面向对象代码,这通常很自然,因为每个操作都会对其找到的对象的任何先前状态进行操作。
说到冲水,留下一个synchronized
block 会导致刷新所有写入数据并输入 synchronized
block 会导致重新读取所有可变数据,但没有 synchronized
的互斥保证在同一实例中,无法控制哪个发生在另一个之前发生。更糟糕的是,您无法使用共享数据来检测情况,因为在不阻塞其他线程的情况下,它仍然可以不一致地修改您正在操作的数据。
由于不同对象上的同步无法建立有效的happens-before关系,因此JVM的优化器不需要维持全局刷新效果。最值得注意的是,如果逃逸分析证明该对象永远不会被其他线程看到,那么今天的 JVM 将取消同步。
因此,您可以在对象上使用同步来保护对存储在其他位置(即不在该对象中)的数据的访问,但它仍然需要在同一对象实例上对同一共享数据的所有访问进行一致的同步,这使程序变得复杂逻辑,与简单地同步包含 protected 数据的同一对象相比。
<小时/> volatile
变量,如 Lock
使用的变量如果线程读取和写入相同的内容,则在内部也具有全局刷新效果 volatile
变量,并使用该值形成正确的程序逻辑。这比 synchronized
更棘手。 block ,因为代码执行没有互斥,或者,您可以将其视为仅限于单个读取、写入或 cas 操作的互斥。
关于java - 根据 java 内存模型,synchronized 到底做了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48041892/
这对你们来说可能很简单,但由于我是java新手,所以我想知道实际上什么是 接下来的部分会发生什么? if (args.length > 0) { file = args[0]; } publi
在我的 View Controller 中,我将 UITapGestureRecognizer 添加到 self.view。我在 self.view 之上添加了一个小 View 。当我点击小 View
我今天尝试从 Obj-C 开始并转到 Swift,我正在阅读文档。我试图在 Swift 中创建一个简单的 IBOutlet,但它不断给我这些错误。 View Controller 没有初始化器 req
我正在尝试使用 VIM 完成(字典和当前缓冲区),但我遇到了问题?和 !在方法名称的末尾。我能以某种方式向 vim 解释方法名称(基本上是单词)最后只能有它,而且只有一个,即 method_name
我是一名优秀的程序员,十分优秀!