概念
- Volatile概念:Volatile關鍵字的主要作用是使變量在多個線程間可見。
- 作用: 在多線程間可以進行變量的變更,使得線程間進行數據的共享可見 阻止指令重排序,happens-before
package com.example.core.cas;import com.example.core.safely.UseThreadLocal;public class UseVolatile extends Thread{private volatile boolean isRunning = true;private void setRunning(boolean isRunning){this.isRunning = isRunning;}public void run(){System.out.println("進入Run方法");while(isRunning == true){//...}System.err.println("線程停止");}public static void main(String[] args) throws InterruptedException{UseVolatile uv = new UseVolatile();uv.start();Thread.sleep(2000);uv.setRunning(false);System.out.println("isRunning的值已經被設置為false");}
}
- ?一個線程可以執行的操作有使用(use)、賦值(assign)、裝載(load)、存儲(store)、鎖定(lock)、解鎖(unlock)。
- 而主內存可以執行的操作有讀(read)、寫(write)、鎖定(lock)、解鎖(unlock),每個操作都是原子的。
- volatile的作用就是強制線程到主內存(共享內存)里去讀取變量,而不去線程工作內存區里去讀取,從而實現了多個線程間的變量可見。也就是滿足線程安全的可見性

JVM
- Java Memory Model(Java 內存模型),簡稱JMM,并發編程這塊,解決一個線程對共享變量的寫入何時對另一個線程可見!
- 比如一個線程給變量 a 賦值 int a = 3; // 向變量 a 寫值 我要解決的問題就是:"在什么條件下,讀取變量a的線程將看到這個值3",如果缺少同步,那會有很多因素使得讀取變量a的線程不能立即看到或者永遠看不到這個值3
- 所有的變量都存儲在主內存中, 每一個線程都有一個私有的本地內存,本地內存中存儲了該線程使用到的變量在主內存中拷貝! 線程對變量的所有操作(讀取、賦值等)都必須在工作內存中進行,而不能直接讀寫主內存中的變量(volatile變量也不例外)
- 如果一個操作執行的結果需要對另一個操作可見,那么這兩個操作之間必須要存在happens-before關系,A=1;B=A;就是A操作的結果要對B操作可見,那么必然存在A happens-before B 簡而言之:使用happens-before的概念來闡述操作之間的內存可見性
- 例如:對一個鎖的解鎖,happens-before 于隨后對這個鎖的加鎖,先后順序很關鍵
指令重排
- JAVA語言為了維持順序內部的順序化語義,也就是為了保證程序的最終運行結果需要和在單線程嚴格意義的順序化環境下執行的結果一致,程序指令的執行順序有可能和代碼的順序不一致,這個過程就稱之為指令的重排序
- 指令重排序的意義在于:JVM能根據處理器的特性,充分利用多級緩存,多核等進行適當的指令重排序,使程序在保證業務運行的同時,充分利用CPU的執行特點,最大的發揮機器的性能
- volatile可以阻止指令的重排序
- 涉及到cpu底層的硬件對于語言的編寫