JAVA内存模型之可见性
可见性定义:
一个线程对共享变量的修改,另一个线程可能不会马上看到。由于多核CPU,每个CPU核都有高速缓存,会缓存共享变量,某个线程对共享变量的修改会改变高速缓存中的值,但却不会马上写入内存。另一个线程读到的是另一个核缓存的共享变量的值,出现缓存不一致问题。
注:以下代码或者图中同步指的是可见
JAVA内存模型之可见性是为解决线程间操作的共享变量访问不一致导致出现问题的一系列规范,是由JVM来执行规范指令,(也就是规范线程间操作)。
volatile
语义是: can not be cached
注:并不是禁止JVM对所有的指令进行重排,只是对影响读数据的情况才会禁止指令重排
懒汉模式实现单例模式加载,为什么使用volatile?
其中synchronized 其实实现了原子性和可见性。
但是当执行到new Singleton()行结束后且synchronized未解锁时,如果有大流量线程访问时,如果不用volatlie修饰变量,大量线程会读到实例为空,会产生等待。相反使用volatjle后实现可见,那么可以大量提升性能。
解锁与加锁
语义解读:
a) 加锁会禁止指令重排
b) 加锁线程对共享变量的操作,当解锁后,对其他抢锁线程是可见的
总结:以上规范其实是对某些变量进行规范,线程操作引起的某些变量值变化,无论读写都是不能缓存的
插播一个变量从主内存被读入工作内存的图
解决共享变量可见性的方式
volatile 上面已经分析
synchronized
每个线程必须去抢一把锁才可能实现可见性。这是实现可见性必要条件