synchronized的内存语义-内存可见性

synchronized的内存可见性很垃圾,慎用,也给了大家一个提醒,synchronized主要是用来互斥,内存可见性尽量用volatile保持

例子

public class TestSyncMemorySee {
          
   
    static boolean r=false;
    static Object o=new Object();

    public static void main(String[] args) {
          
   
        Thread t1=new Thread(()->{
          
   
           synchronized (o){
          
   
               while (!r){
          
   }
           }
            System.out.println(Thread.currentThread().getName()+"end");
        },"t1");

        Thread t2=new Thread(()->{
          
   
            r=true;
            System.out.println(Thread.currentThread().getName()+"end");
        },"t2");

        t1.start();
        try {
          
   
            Thread.sleep(1000);
        } catch (InterruptedException e) {
          
   
            e.printStackTrace();
        }
        t2.start();

    }
}

上面代码t1线程先开始执行,按照synchoinzed的内存可见性,获取锁后会刷新工作内存,从主内存拉取共享变量r=false,后面这个值是不会改变的,就算t2线程在1秒后改变了r=true,但是t1线程还在傻循环,由此可以推测synchronized的内存可见性只限于一次读取,解决办法是r变量加volatile修饰,volatile的内存可见性是无论什么时候读都是通过刷新工作内存,从主内存读取,底层是通过总线锁实现,汇编指令是lock。synchorinzed保持内存可见性底层还不太清楚,推测是简单的一次刷新工作内存,没有在cpu加锁

经验分享 程序员 微信小程序 职场和发展