0
点赞
收藏
分享

微信扫一扫

volatile 的内存语义

young_d807 2022-02-26 阅读 56

volatile 的内存语义

volatile 修饰的变量具有以下特性:

  • 可见性。对一个 volatile 变量的读,总是能看到任意线程对这个 volatile 变量最后的写入。
  • 原子性。对任意单个 volatile 变量的读/写具有原子性(除去 double 和 float 类型变量,因为这两种类型变量为 64 位类型)。

一个 volatile 变量的单个读/写操作,与锁对普通变量的读/写,它们之间的执行效果相同。

volatile 的 happens-before 规则:一个 volatile 的写 happens-before 于volatile 的读。

volatile 写–读建立的 happens-before 关系

	class ReorderExample {
	    int a = 0;
	    boolean flag = false;
	    
		public void writer() {
			a = 1;       // 1
			flag = true; // 2
		}
	
		public void reader() {
		    if(flag) {         // 3
		        int i = a * a; // 4
		    }
		}
	}

假设线程 A 执行 writer() 方法之后,线程 B 执行 reader() 方法。根据 happnes-before 规则进行分析:
1)根据程序次序规则,1 happens-before 2;3 happens-before 4。
2)根据 volatile 规则,2 happens-before 3。
3)根据 happens-before 的传递性规则,1 happens-before 4。

volatile 的内存语义

volatile 的线程通信理解:
volatile 变量修改后,因为 volatile 的读总能看到 volatile 的写,在对 volatile 修饰变量进行写入操作时,本地内存中的共享变量进行修改后直接刷新到主内存;此时进行 volatile 读时,本地内存直接无效化,需要重新从主内存中获取。即 volatile 的一次写读就是线程之间进行一次通信,保证数据正确。

volatile 内存语义的实现

总结

读 volatile 操作通过将其他线程的本地内存无效化,强制从主内存中获取数据,达到数据实时更新效果。通过该方式,volatile 的写与读操作相当于线程间进行隐式通信。

引申一点,锁的内存语义与 volatile 一致,释放锁后数据必须对获取锁可见。

举报

相关推荐

0 条评论