synchronized和volatile其实不是一个东西,volatile不能确保原子性,自然就不能锁住资源了。
1、 volatile到底做了什么:
1、 禁止了指令重排
2、保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量值,这个新值对其他线程是立即可见的
不保证原子性(线程不安全)
什么是缓存一致性协议呢?
每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里
volatile是两条实现原则:
1.Lock前缀指令会引起处理器缓存会写到内存
当对volatile变量进行写操作的时候,JVM会向处理器发送一条lock前缀的指令,将这个缓存中的变量回写到系统主存中
2.一个处理器的缓存回写到内存会导致其他处理器的缓存失效
处理器使用嗅探技术保证内部缓存 系统内存和其他处理器的缓存的数据在总线上保持一致。
综合上面两条实现原则,我们了解到:如果一个变量被volatile所修饰的话,在每次数据变化之后,其值都会被强制刷入主存。而其他处理器的缓存由于遵守了缓存一致性协议,也会把这个变量的值从主存加载到自己的缓存中。这就保证了一个volatile在并发编程中,其值在多个缓存中是可见的。
为了保证内存的可见性,除了缓存一致性协议还有一个happends-before关系
注意:
数组与对象实例中的 volatile,针对的是引用,对象获数组的地址具有可见性,但是数组或对象内部的成员改变不具备可见性
存在四种读写屏障 保证禁止指令重排序