在读写原子性,可见性和防止重新排序方面,Java中的锁,同步,原子变量和易失性 [英] Lock vs synchronized vs atomic variables vs volatile in java in terms of read-write atomicity, visibility and protection from reordering
问题描述
我从《 Java并发实践》一书中阅读了有关volatile
的以下内容:
I read following about volatile
from the book Java Concurrency in Practice:
当一个字段被声明为volatile时,编译器和运行时会被注意,该变量是共享的,并且对该变量的操作不应与其他内存操作重新排序.易失性变量不会缓存在寄存器中,也不会缓存在对其他处理器隐藏的缓存中,因此读取 volatile变量始终返回任何线程的最新写入.
When a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.
易失性变量的可见性影响超出了易失性变量本身的值.当线程A写入易失性变量,随后线程B读取相同的变量时,在读取易失性变量后,在写入易失性变量之前A可见的所有变量的值对B都是可见的.因此,从内存可见性的角度来看,写入volatile变量就像退出同步块,而读取volatile变量就像进入同步块.
The visibility effects of volatile variables extend beyond the value of the volatile variable itself. When thread A writes to a volatile variable and subsequently thread B reads that same variable, the values of all variables that were visible to A prior to writing to the volatile variable become visible to B after reading the volatile variable. So from a memory visibility perspective, writing a volatile variable is like exiting a synchronized block and reading a volatile variable is like entering a synchronized block.
我对上面的最后一句话感到困惑.假设变量x
被定义为volatile
,并且在修改x
,u
,v
和w
对线程A
可见之前,然后当线程B
之后读取x
时,它将还可以读取u
,v
和w
的最新值.我们可以为synchronized
指定相同的名称吗?
I am confused with the last sentence above. Say variable x
is defined volatile
and before modifying x
, u
,v
and w
were visible to thread A
, then when thread B
reads x
afterwards, it will also be able to read latest values of u
,v
and w
. Can we specify for same for synchronized
?.
第1季度.也就是说,下面的答案正确吗?
Q1. That is, is below correct?
变量
u
,v
和w
在退出synchronized
块时对线程A
是可见的,因此u
,v
和w
的最新值对线程可见B
之后输入synchronized
块.
Variables
u
,v
andw
were visible to threadA
while exitingsynchronized
block, then the latest values ofu
,v
andw
will be visible to threadB
enteringsynchronized
block afterwards.
我觉得上述事实是不正确的,因为u
,v
和w
可能存储在缓存和寄存器中,因为它们没有定义为volatile
.我对此正确吗?因此synchronized
(以及locks
和atomic
变量也不能保证可见性,因为它们与synchronized
相似)
I feel above fact is incorrect as u
,v
and w
may be stored in caches and registers as they are not defined volatile
. Am I correct with this? So visibility is not ensured by synchronized
(and also by locks
and atomic
variables as they are similar to synchronized
)
这本书进一步说:
锁定可以保证可见性和原子性. volatile变量只能保证可见性.
Locking can guarantee both visibility and atomicity; volatile variables can only guarantee visibility.
但是我有以下感受:
- 锁,
synchronized
和原子变量仅保证读写原子性(不保证可见性和防止重新排序). -
volatile
保证可见性并防止编译器和运行时对其进行重新排序(不是读写原子性).
- Locks,
synchronized
and atomic variables only guarantee read-write atomicity (not visibility and protection from reordering). volatile
guarantee visibility and protection from reordering by compiler and runtime (not read-write atomicity).
第二季度.我对以上两点都正确吗?
Q2. Am I correct with above two points?
推荐答案
1)锁,同步变量和原子变量可保证读写原子性和 可见性和防止重新排序
1) Locks, synchronized and atomic variables guarantee read-write atomicity and visibility and protection from reordering
2)volatile保证可见性并防止编译器和运行时重新排序
2) volatile guarantees visibility and protection from reordering by compiler and runtime
易失性字段的读写原子性有些棘手:对易失性字段的读写是原子性的,例如,如果您在32位jvm上对易失性long(64位)进行写操作,则读和写操作为仍然是原子的.您总是会阅读完整的64位.但是像volatile int或long这样的操作不是原子
read-write atomicity of volatile fields is a little bit tricky: reading and writing to a volatile field is atomic, for example if you write to a volatile long (64 bit) on a 32 bit jvm the read and the write is still atomic. You always read the complete 64 bit. But operations like ++ on a volatile int or long are not atomic
这篇关于在读写原子性,可见性和防止重新排序方面,Java中的锁,同步,原子变量和易失性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!