java并发编程-volatile关键字
并发编程
MESI协议
基于失效的缓存一致性协议
有四个状态:
- Exclusive(E):独享,其他缓存都没有有效的副本
- Shared(S):共享,其他缓存都有有效的副本
- Invalid(I):失效
- Modified(M):修改
原子性、有序性、可见性
原子性
在java中,对基本数据类型的变量读取和赋值操作是原子性操作,这些操作是不可中断的,也就是要么读,要么不读,或者要么写要么不写。
1 | x = 10; // 操作1 |
以上的操作中只有操作1属于原子性操作。
有序性
有以下这样的代码:
1 | int x = 10; |
当有volatile关键字修饰时,会看到在程序运行时的汇编指令中会发现有locak指令,相当于一个内存屏障,会强制把缓存的操作写入主存。
当不能保证有序性时,打印输出的结果可能为false。所以在程序运行必须保证有序性。
可见性
在Java中,提供了volatile关键保证可见性。
当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。
此外,通过synchronized和Lock也能够保证可见性,synchronized和Lock能保证同一时刻只有一个线程获取锁然后执行同步代码,并且在释放锁之前会将对变量的修改刷新到主存当中。因此可以保证可见性。
volatile、synchronized
volatile可以保证对变量操作的有序性、可见性,但是不能保证原子性
synchronized可以保证对变量的有序性、可见性、原子性