This question already has answers here:
Java volatile modifier and synchronized blocks
(3个答案)
去年关闭。
我正在阅读有关Java中的同步和易失性的信息。每篇新文章都使我感到困惑。一篇文章说“ Java的同步关键字保证了互斥和可见性”。我不确定能见度部分。 Java中的volatile是否可以解决可见性问题?让我们考虑这个小程序。
可以说这是由10个线程运行的,其中5个用于读取,而5个由写入在同一SharedObj对象上运行。
在这里,我们既需要同步又需要波动?
volatile:因为每个线程都会将sharedVar缓存到本地缓存中。
同步:一次一个线程。
(3个答案)
去年关闭。
我正在阅读有关Java中的同步和易失性的信息。每篇新文章都使我感到困惑。一篇文章说“ Java的同步关键字保证了互斥和可见性”。我不确定能见度部分。 Java中的volatile是否可以解决可见性问题?让我们考虑这个小程序。
class SharedObj
{
volatile int sharedVar = 6;
public int synchronized getVar(){
return sharedVar;
}
public synchronized setVar(int i){
return sharedVar=i;
}
}
可以说这是由10个线程运行的,其中5个用于读取,而5个由写入在同一SharedObj对象上运行。
在这里,我们既需要同步又需要波动?
volatile:因为每个线程都会将sharedVar缓存到本地缓存中。
同步:一次一个线程。
最佳答案
锁定可以保证可见性和原子性。 volatile变量只能保证可见性
能见度有什么问题? CPU内核具有缓存,当内核要将数据写入内存时,它首先会写入缓存,这意味着,即使一个内核认为将新值写入变量,其他线程仍然可以观察到旧值(所谓的“陈旧数据” )。
输入同步块有以下副作用:缓存无效-从主存储器中获取变量的新值。
离开同步块有以下副作用:所有缓存的数据都将刷新到主存储器。
在您的小示例中:使用sharedVar
设置图像线程1的值setVar
。由于此方法是synchronized
,因此sharedVar
的值将在方法结束时刷新到主内存中。当线程2要使用getVar
读取值时,它首先从主内存中获取sharedVar
值-并且我们知道该值是最新的。因此,此处volatile
关键字是多余的。
顺便说一句,从volatile
变量读取与退出同步块具有相同的副作用:不仅刷新volatile
变量值,其他变量也被刷新;写入volatile
变量与进入同步块具有相同的副作用:不仅会获取volatile
变量值,还会获取其他变量。
布莱恩·格茨(Brian Goetz)的伟大著作Java concurrency in practice
的第一章对一切进行了完美的解释。
07-27 19:54