Java Volatile关键字
volatile通过保证对变量的读或写都是直接从内存中读取或直接写入内存中,保证了可见性;但是volatile并不足以保证线程安全,因为无法保证原子性,如count++操作:
- 将值从内存读入寄存器中
- 进行加1操作,内存保存到寄存器中
- 结果从寄存器flush到内存中
借用一张图来看:
不是volatile的变量的指令执行顺序是1->2->3;而声明为volatile的变量,顺序是1->23。从这里看,volatile保证了一个线程修改了volatile修饰的变量,变化会马上体现在内存中。线程间看到的值是一样的。
上面说了无法保证原子性是指:多核cpu,线程A执行了指令1,线程B也执行了指令1。A进行了加1操作,结果写入寄存器同时flush到内存;随后B也执行了同样的操作。count本来应该的结果是加2,但是却只加了1。原因就是我们通常所指的读和写不是原子操作。我们最希望看到的是123同时执行,手段就是sychronized或者java.util.concurrent包中的原子数据类型。
简单拿AtomicInteger来看,其中的一个int类型的value字段声明为volatile,保证了123同时执行。