我正在阅读有关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对象上运行。 在这里,我们既需要同步又需要不稳定?
易失性:因为每个线程都会将sharedVar缓存到本地缓存中。
已同步:一次一个线程。
答案 0 :(得分:1)
锁定可以保证可见性和原子性。易变变量只能保证可见性
可见性有什么问题? CPU内核具有缓存,当内核要将数据写入内存时,它首先会写入缓存,这意味着,即使一个内核认为将新值写入变量,其他线程仍然可以观察到旧值(所谓的“陈旧数据” )。
进入同步块有以下副作用:缓存无效-从主存储器中获取变量的新值。
离开同步块有以下副作用:所有缓存的数据都被刷新到主存储器中。
在您的小示例中:使用sharedVar
设置图像线程1的值setVar
。由于此方法为synchronized
,因此sharedVar
的值将在方法结束时刷新到主内存。当线程2要使用getVar
读取值时,它首先从主内存中获取sharedVar
值-我们知道,该值是最新的。因此,这里的volatile
关键字是多余的。
顺便说一下,从volatile
变量读取具有与离开同步块相同的副作用:不仅volatile
变量值被刷新,其他变量也被刷新;并写入volatile
变量与进入同步块具有相同的副作用:不仅会获取volatile
变量值,还会获取其他变量;
在布莱恩·格茨(Brian Goetz)伟大的书Java concurrency in practice
的第一章中,一切都得到了完美的解释。