聊聊 JAVA 中的 Volatile

Volatile是一种轻量级的同步机制,它有两个主要特性:安全

  1. 保证共享变量对全部线程的可见性。
  2. 禁止指令重排序优化。

一. 保证共享变量对全部线程的可见性多线程

public class TestVolatile {	
	volatile boolean status = false;// 关键代码 

	/**
	 * 状态切换为true
	 */
	public void changeStatus(){
		status = true;
	}

	/**
	 * 若状态为true,则running。
	 */
	public void run(){
		if(status){
			System.out.println("running....");
		}
	}
}

解析函数

  • 1.关键代码处不加volatile的效果

不加,若是在多线程机制下, 在JVM 中 status是一个线程,run方法是另一个线程,两个线程之间互不通信,所以无法保证执行完changestatus后,run函数会运行。优化

  • 2.关键代码处加了volatile的效果

加了,则把status变量提高成内存共享变量,线程之间能够互访,所以在多线程环境下,也能保证run方法确定会执行。线程


P.S Volatile并不能彻底替代Synchronized,它依然是个轻量级锁,在不少场景下,Volatile并不能胜任,譬如在复合类的操做下,没法确保线程安全。 例如:num++,这是一个复合型操做,拆解步骤就是:code

  1. 取值
  2. 加法运算
  3. 赋值

Volatile 只能保证原子性操做的线程安全,对于复合型操做则没法起到预期的目的,关于这点的改进,能够参考Volatile的第二特征,也能够借鉴 JAVA AtomicInteger 源代码,利用的也是Volatile的第二特征。排序


二.禁止指令重排序优化内存

Volatile指令的排序规则:编译器

  1. 当第二个操做是voaltile写时,不管第一个操做是什么,都不能进行重排序。
  2. 当地一个操做是volatile读时,无论第二个操做是什么,都不能进行重排序。
  3. 当第一个操做是volatile写时,第二个操做是volatile读时,不能进行重排序。

`同步

int a = 1;  // 1
int b = 2; //2
int c = a + b; // 3

`

解析

  • a,b 直接赋值,不存在数据依赖,所以 // 1,2 编译器或解析器对这两处的代码能够存在重排序优化。
  • c 存在数据依赖,依赖a,b;所以不存在数据依赖。
  • 若是要保证a,b 按顺序执行,加上 Volatile 便可,限制编译器或解析器对其进行排序优化。
相关文章
相关标签/搜索