首先看一個例子
package cn.lazyfennec.demo.example;
import java.util.concurrent.TimeUnit;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/6/15 11:39
*/
public class VisibilityDemo {
public boolean flag = true;
public static void main(String[] args) throws InterruptedException {
VisibilityDemo demo = new VisibilityDemo();
System.out.println("代碼開始了~~~~");
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(demo.flag) {
i++;
}
System.out.println(i);
}
});
thread.start();
TimeUnit.SECONDS.sleep(2);
demo.flag = false;
System.out.println("flag 被置為 false 了");
}
}
以上的代碼我衬,在不看運行結(jié)果的情況下,按照邏輯分析院刁,最后的結(jié)果大致如下
代碼開始了~~~~
flag 被置為 false 了
*** // 這里***表示某個值
但是實際的執(zhí)行結(jié)果是這樣的
代碼開始了~~~~
flag 被置為 false 了
// 這里進入了死循環(huán)
volatile 關(guān)鍵字
-
可見性問題
讓一個線程對共享變量的修改旗笔,能夠及時的被其他線程看到。
- Java內(nèi)存模型規(guī)定:
對 volatile 變量v的寫入撑螺,與所有其他線程后續(xù)對 v 的讀同步
要滿足以上條件,volatile關(guān)鍵字需要有以下的功能
禁止緩存
volatile變量的訪問控制符會加個ACC_VOLATILE
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5對
volatile
變量相關(guān)的指令不做重排序
即JVM在進行編譯的時候崎弃,正常情況下实蓬,會在JVM規(guī)定的規(guī)范內(nèi),對指令進行重排序吊履,以提高運行效率(性能)安皱,而對于volatile修飾的內(nèi)容,則不會進行重新排序艇炎。
- 對于以上的問題酌伊,在flag變量前加入volatile關(guān)鍵字
public volatile boolean flag = true;
此時的執(zhí)行結(jié)果
代碼開始了~~~~
flag 被置為 false 了
30024084
擴展: Shared Variables 共享變量定義
可以在線程之間共享的內(nèi)存稱為共享內(nèi)存或堆內(nèi)存。
所有實例字段缀踪、靜態(tài)字段和數(shù)組元素都存儲在堆內(nèi)存中居砖,這些字段和數(shù)組都是標題中提到的共享變量。
沖突:如果至少有一個訪問是寫操作驴娃,那么對同一個變量的兩次訪問是沖突的奏候。
這些能被多個線程訪問的共享變量是內(nèi)存模型規(guī)范的對象。
定義在: https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4.1
如果覺得有收獲就點個贊吧唇敞,更多知識蔗草,請點擊關(guān)注查看我的主頁信息哦~