java为什么我需要在volatile上对多个线程使用synchronized?
有些人说,如果多个线程正在读/写,那么您需要使用synchronized;如果一个线程正在读/写,而另一个线程仅在读,那么您必须使用volatile。我不明白这两种情况之间的区别
基本上,一个volatile字段的值在写操作完成后对所有读卡器(特别是其他线程)都可见
然后,如果我将一个变量定义为volatile,首先threadA将读取它的值,threadA将更新它的值并将其写入内存。之后,threadB将看到该变量。那为什么我需要同步块呢
# 1 楼答案
这真的没有硬性规定。选择是否使用
synchronized
或volatile
与对象的更新方式(而不是读写器的数量)有更多关系例如,您可以使用
AtomicLong
实现多个读写器,该volatile long
封装了volatile long
在某些情况下,即使只有一个读写器,也需要一个
synchronized
块在上面的示例中,由于我们正在进行多个调用来更新
status
对象,因此我们可能需要确保其他线程在更新num事务(而不是总金额)时不会看到它。是的,AtomicReference
处理其中一些案例,但不是全部明确地说,标记字段
volatile
可以确保内存同步。当您读取volatile
字段时,您会跨越一个读取内存屏障,而当您写入它时,您会跨越一个写入内存屏障。synchronized
块的开头有一个读内存屏障,结尾有一个写屏障,和具有互斥锁,以确保一次只能有一个线程进入该块有时您只需要内存屏障来实现线程之间的数据共享,有时您需要锁定
# 2 楼答案
volatile和synchronized之间的主要区别在于volatile只保证可见性,而synchronized同时保证可见性和锁定
如果有多个读线程和一个写线程,那么volatile用法可以确保写线程对volatile变量的更改对其他线程立即可见。但在本例中,锁定不是问题,因为您只有一个写入线程
对于易失性,有一些经验法则:
一般来说,volatile的使用应该仅限于那些相对容易解释其状态的情况,例如状态标志的情况
在所有其他具有共享可变状态的情况下,除非声明为final并仅在构造函数中修改,否则在触及共享可变状态的任何位置都始终使用synchronized,而不使用不安全的发布。Volatile仅在特殊情况下替代synchronized,如我的3点所述
# 3 楼答案
正如评论所建议的,你可以做一些进一步的阅读。但是为了给你一个想法,你可以看看这个stackoverflow question并思考以下场景:
有几个变量需要处于正确的状态。但是,尽管您使它们都不稳定,但您需要时间通过执行一些代码来更新它们
这段代码几乎可以由不同的线程同时执行。第一个变量可能是“OK”的,并且以某种方式进行了同步,但是其他一些变量可能依赖于第一个变量,并且还不正确。因此,在这种情况下需要一个同步块
为了进一步阅读volatilelook here,再添加一篇文章