volatile关键字的特点
1)保证变量的可见性
也就是保证CPU在执行程序过程中,被volatile修饰的变量不再从高速缓存中找,而是直接从主存中寻找,从而保证每次都是变量最新的数据
2)保证有序性
JVM为了高效率的执行java程序,在不影响结果一致的情况下会对编译后的执行进行“重排序”。加入volatile关键字之后会保证该变量从创建到修改到使用的过程,JVM不会对其中的执行进行重排序,从而保证了有序性。
3)不保证原子性
意思就是即使共享变量被volatile关键字修饰,也不能保证该共享变量是线程安全的。比如多线程情况下执行i=i+10(初始为0)操作时。线程A先把i=0导入到CPU中,然后让出CPU,线程B开始执行,同样是i=0,执行加法之后把i写入到主存中。线程A继续执行,同样执行加法把i写回,从而出现问题。
public class VolatileTest {
private static int i=0;
public static void main(String[] args) {
new Thread(()->{
while(i<1000){
System.out.println(Thread.currentThread().getName()+">>"+(++i));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"T1").start();
new Thread(()->{
while(i<1000){
System.out.println(Thread.currentThread().getName()+">>"+(++i));
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"T2").start();
}
}
结果如下:
出现了两个3。