[英]redundant volatile in cheap read-write lock?
Brian Goetz in his article from https://www.ibm.com/developerworks/java/library/j-jtp06197/ Brian Goetz在他的文章中来自https://www.ibm.com/developerworks/java/library/j-jtp06197/
uses the example pasted below as a cheap read-write lock. 使用下面粘贴的示例作为便宜的读写锁。 My question is that if the int variable value is not declared volatile then would it make a difference?
我的问题是,如果不将int变量值声明为volatile,那会有所作为吗? My understanding is that since the writes to value are done within a synchronized block so latest value will be visible to other threads any way and therefore declaring it volatile is redundant.
我的理解是,由于对值的写入是在同步块内完成的,因此最新值将以任何方式对其他线程可见,因此将其声明为volatile是多余的。 Please clarify?
请澄清?
@ThreadSafe
public class CheesyCounter {
// Employs the cheap read-write lock trick
// All mutative operations MUST be done with the 'this' lock held
@GuardedBy("this") private volatile int value;
public int getValue() { return value; }
public synchronized int increment() {
return value++;
}
} }
public synchronized int increment()
This synchronized
prevents you from skipping an increment if two threads or more were trying to increment at the same time (because ++
is not atomic). 如果两个或两个以上线程试图同时递增(因为
++
不是原子的),则此synchronized
可防止您跳过递增。
private volatile int value
This prevents you from seeing an outdated value in one thread which was already incremented in another thread. 这样可以防止您在一个线程中看到过时的值,而该值在另一个线程中已递增。 (Note that we could also have made getValue synchronized to achieve this)
(请注意,我们也可以使getValue同步以实现此目的)
My understanding is that since the writes to value are done within a synchronized block so latest value will be visible to other threads any way
我的理解是,由于对值的写入是在同步块内完成的,因此最新值将以任何方式对其他线程可见
This is incorrect. 这是不正确的。 Generally, there is no guarantee that other threads "see" changes to variables as soon as the change is made.
通常,不能保证其他线程在进行更改后就立即“看到”对变量的更改。 A thread may see a stale value for a changed variable because, eg the thread sees the value really in a register instead of main memory.
线程可能会看到已更改变量的过时值,因为例如,线程实际上在寄存器中而不是在主存储器中看到了该值。
A volatile
variable establishes "happens-before" semantics. volatile
变量建立“先于发生”的语义。 The JLS, section 17.4.5 , states: JLS第17.4.5节指出:
Two actions can be ordered by a happens-before relationship.
可以通过事前发生关系来排序两个动作。 If one action happens-before another, then the first is visible to and ordered before the second.
如果一个动作发生在另一个动作之前 ,则第一个动作对第二个动作可见,并在第二个动作之前排序。
- A write to a
volatile
field (§8.3.1.4) happens-before every subsequent read of that field.在随后每次对该字段进行读取之前,都会写入一个
volatile
字段(第8.3.1.4节)。
The JLS, Section 8.3.1.4 : JLS,第8.3.1.4节 :
A field may be declared
volatile
, in which case the Java Memory Model ensures that all threads see a consistent value for the variable (§17.4).可以将字段声明为
volatile
,在这种情况下,Java内存模型可确保所有线程看到的变量值均一致(第17.4节)。
The reason that the field must be volatile
is that even though the read is atomic, it needs to ensure that the value is current -- that any value previously written by another thread is visible. 该字段必须是
volatile
的原因是,即使读取是原子的,它也需要确保该值是最新的-先前由另一个线程写入的任何值都是可见的。 The read being atomic is not enough; 读是原子的还不够;
volatile
is still necessary to ensure consistency of the value. 为了确保值的一致性,仍然必须使用
volatile
。
Thanks very much for the answers guys. 非常感谢你们的答案。 Found this on oracle website as well now: "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."
现在在oracle网站上也发现了这一点:“其次,当同步方法退出时,它会自动与任何后续调用同一对象的同步方法建立先发生后关系。” https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.