同步标记是否会自动可变挥发?

时间:2018-09-23 11:53:28

标签: java synchronized volatile

我正在阅读有关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缓存到本地缓存中。

已同步:一次一个线程。

1 个答案:

答案 0 :(得分:1)

  

锁定可以保证可见性和原子性。易变变量只能保证可见性

可见性有什么问题? CPU内核具有缓存,当内核要将数据写入内存时,它首先会写入缓存,这意味着,即使一个内核认为将新值写入变量,其他线程仍然可以观察到旧值(所谓的“陈旧数据” )。

进入同步块有以下副作用:缓存无效-从主存储器中获取变量的新值。

离开同步块有以下副作用:所有缓存的数据都被刷新到主存储器中。

在您的小示例中:使用sharedVar设置图像线程1的值setVar。由于此方法为synchronized,因此sharedVar的值将在方法结束时刷新到主内存。当线程2要使用getVar读取值时,它首先从主内存中获取sharedVar值-我们知道,该值是最新的。因此,这里的volatile关键字是多余的。


顺便说一下,从volatile变量读取具有与离开同步块相同的副作用:不仅volatile变量值被刷新,其他变量也被刷新;并写入volatile变量与进入同步块具有相同的副作用:不仅会获取volatile变量值,还会获取其他变量;

在布莱恩·格茨(Brian Goetz)伟大的书Java concurrency in practice的第一章中,一切都得到了完美的解释。