This question already has answers here:
Java volatile modifier and synchronized blocks
                                
                                    (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