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加锁