volatile
- OpenJDKunsafe.cppvolatilelock:
- LockLockLockCPUCPULock
- CPU里缓存了该地址的数据无效
Thread-A与Threab-B同时操作主存中的一个volatile变量i时,Thread-Ai
- Thread-A发出LOCK#指令
- LOCK#指令锁总线(或锁缓存行)CPU不能访问总线,不能访问总线就意味着不能访问系统内存)Thread-B高速缓存中的
- Thread-A向主存回写最新修改的i
Thread-B读取变量i,那么:
- Thread-B发现对应地址的
volatile关键字的读和普通变量的读取相比基本没差别,差别主要还是在变量的写操作上。
为什么static volatile int i = 0; i++;不保证线程安全?
i++并不是一个原子操作i++本身特质决定的
1、获取i
2、i自增
3、回写i
A、B两个线程同时自增i
由于volatile可见性,因此步骤1ii
2步开始就有问题了,有可能出现的场景是线程A自增了i并回写,但是线程B此时已经拿到了i,不会再去拿线程A回写的i,因此对原值进行了一次自增并回写
A对i进行自增了以后cpu缓存不是应该通知其他缓存,并且重新load i么?
A对i进行了自增,线程B已经拿到了i并不存在需要再次读取i的场景,当然是不会重新load i这个值的。
ps:也就是线程B的缓存行内容的确会失效。但是此时线程B中i的值已经运行在加法指令中,不存在需要再次从缓存行读取i的场景。