在读写原子性,可见性和防止重新排序方面,Java中的锁,同步,原子变量和易失性 [英] Lock vs synchronized vs atomic variables vs volatile in java in terms of read-write atomicity, visibility and protection from reordering

查看:112
本文介绍了在读写原子性,可见性和防止重新排序方面,Java中的锁,同步,原子变量和易失性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从《 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,并且在修改xuvw对线程A可见之前,然后当线程B之后读取x时,它将还可以读取uvw的最新值.我们可以为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?

变量uvw在退出synchronized块时对线程A是可见的,因此uvw的最新值对线程可见B之后输入synchronized块.

Variables u,v and w were visible to thread A while exiting synchronized block, then the latest values of u,v and w will be visible to thread B entering synchronized block afterwards.

我觉得上述事实是不正确的,因为uvw可能存储在缓存和寄存器中,因为它们没有定义为volatile.我对此正确吗?因此synchronized(以及locksatomic变量也不能保证可见性,因为它们与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.

但是我有以下感受:

  1. 锁,synchronized和原子变量仅保证读写原子性(不保证可见性和防止重新排序).
  2. volatile保证可见性并防止编译器和运行时对其进行重新排序(不是读写原子性).
  1. Locks, synchronized and atomic variables only guarantee read-write atomicity (not visibility and protection from reordering).
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆