volatile是Java虚拟机提供的轻量级的同步机制
3大特性
1.保证可见性
当多个线程同时访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值
案例代码
import java.util.concurrent.TimeUnit; class MyData { // int number = 0; volatile int number = 0; public void add() { this.number = 60; } } public class VolatileDemo { public static void main(String[] args) { MyData myData = new MyData(); new Thread(() -> { System.out.println(Thread.currentThread().getName() + " come in"); try { // 暂停一下线程 TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } myData.add(); System.out.println(Thread.currentThread().getName() + " updated number value:" + myData.number); }, "AAA").start(); // 第2个线程就是main线程 while (myData.number == 0) { // main线程一直在这里等待循环,直到number != 0 } // System.out.println(Thread.currentThread().getName()+" mission is over"); System.out.println(Thread.currentThread().getName() + " mission is over, number value:" + myData.number); } }
结果:
AAA come in
AAA updated number value:60
加了volatile关键字的结果:
AAA come in
AAA updated number value:60
main mission is over, number value:60
2.不保证原子性
原子性:一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行
案例代码
import java.util.concurrent.TimeUnit; class MyData { volatile int number = 0; public void add() { this.number = 60; } // 此时number是有volatile修饰的 public void addPlus() { number++; } } public class VolatileDemo { public static void main(String[] args) { MyData myData = new MyData(); for (int i = 1; i <= 20; i++) { new Thread(() -> { for (int j = 1; j <= 1000; j++) { myData.addPlus(); } }, String.valueOf(i)).start(); } while (Thread.activeCount() > 2) { Thread.yield(); } System.out.println(Thread.currentThread().getName() + " finally number value:" + myData.number); } }
结果:
main finally number value:19909 main finally number value:18330 main finally number value:19904
结论:每次运行结果都不相同,所以volatile不保证原子性
3.禁止指令重排
指令重排序:是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。
在Jvm执行中,指令重排在多个线程同时访问一个普通变量的情况下,可能导致程序执行结果发视错误,而volatile可以避免这种错误发生。