JAVA提供了volatile关键字,用于修饰变量。
1.保证变量对所有线程的可见性
当一个线程修改了变量的值,会强制同步到内存,这样其它线程能够立即读取它的值。
2.禁止指令重排
通过插入内存屏障禁止CPU重新排序指令。
volatile翻译为:不稳定的、易变的;
含义可以理解为:变量的值可能随时会别的线程修改,保证其它线程能读取到修改后的值。
volatile能具备可见性、有序性,但不具备原子性。
适用场景:
线程循环标志位变量;
单例模式中的实例变量;
读多写少,写操作不依赖当前值。
JDK中应用:
ConcurrentHashMap的Entry的value和next被声明为volatile;
AtomicLong中的value被声明为volatile。
对比synchronized关键字:
volatile不具体原子性,因此不能保证多线程读写数据时数据的一致性;
但它不阻塞线程,性能高于synchronized。
JAVA内存模型
内存、CPU缓存
当对非volatile变量进行读写的时候,每个线程先从内存拷贝变量到CPU缓存;
如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着变量可能拷贝到不同的CPU缓存;
1.可见性
指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。
2.原子性
指操作的最小单位,是不可分割的。
例:
原子性操作 a=0;
非原子性 a++;
3.有序性
指令是按顺序串行执行的。
程序执行时按照代码书写的先后顺序执行;
在Java内存模型中,允许编译器和处理器对指令进行重排序;
重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性。