Java并發(fā)編程中的volatile關(guān)鍵字詳解
一、什么是 JMM
JMM 是 Java 內(nèi)存模型的縮寫,其將 Java 運行的底層內(nèi)存模型抽象成了 主存 和 工作內(nèi)存。
其中, 主存就是線程共享的內(nèi)存, 工作內(nèi)存就是線程所私有的內(nèi)存 。
二、什么是可見性
可見性是指放在主存中的內(nèi)容所有線程都是可見的 。
但是由于 JIT (即時編譯器)的存在,有時我們放在主存中內(nèi)容,會被其移動到工作內(nèi)存給某個線程私有 。
三、引出 volitale
1. volatile 用來做什么
volatile 用于保證我們某個變量的可見性,使其一直存放在主存中,不被移動到某個線程的私有工作內(nèi)存中。
synchronized 也能實現(xiàn)可見性,但是麻煩,沒有 volatile 簡潔,而且更加重量級,會降低效率
2. 舉個例子,怎么使用
volatile 可以用來修飾 :
- 成員變量
- 靜態(tài)成員變量
使用實例
public class TestVolatile { volatile static boolean use = true; public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { while (use){ // 執(zhí)行相應(yīng)操作 } }); thread.start(); // 主線程休眠一秒 sleep(1000); use = false; } }
3. volatile 可以保證原子性嘛
不能,它只能保證可見性,不能保證原子性 。
四、 volatile 原理 (JDK 1.5 之后)
內(nèi)存屏障技術(shù), Memory Barrier
- 寫指令,加入寫屏障
- 讀指令,加入讀屏障
1. 保證可見性
- 寫屏障保證在該屏障之前,對共享變量的改動,都同步到主存中
- 讀屏障保證在該屏障之后,對共享變量的讀取,加載的是主存中的最新數(shù)據(jù)
2. 保證有序性
- 寫屏障確保指令重排時,不會將寫屏障之前的代碼排在寫屏障之后
- 讀屏障確保指令重排時,不能將讀屏障之前的代碼排在讀屏障之后
3. 解決 dcl 問題 (double-checked locking)
public class Singleton { private Singleton() {} private static Singleton INSTANCE = null; public static Singleton getINSTANCE(){ if(INSTANCE == null){ synchronized (Singleton.class) { if(INSTANCE == null) { // 會因為指令重排序出現(xiàn)問題 INSTANCE = new Singleton(); } } } return INSTANCE; } }
解決 dcl 問題
為共享變量加上 volatile 關(guān)鍵字,從而避免指令重排序的問題 。 (jvm 可能對指令進(jìn)行重排序,重排序可以會在多線程并發(fā)時出現(xiàn)問題)
到此這篇關(guān)于Java并發(fā)編程中的volatile關(guān)鍵字詳解的文章就介紹到這了,更多相關(guān)Java中的volitale關(guān)鍵字內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot使用Redis中ZSetOperations實現(xiàn)博客訪問量
在日常的網(wǎng)站使用中,經(jīng)常會碰到頁面的訪問量,本文主要介紹了Springboot使用Redis中ZSetOperations實現(xiàn)博客訪問量,具有一定的參考價值,感興趣的可以了解一下2024-01-01SpringMVC攔截器——實現(xiàn)登錄驗證攔截器的示例代碼
本篇文章主要介紹了SpringMVC攔截器——實現(xiàn)登錄驗證攔截器的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-02-02SpringBoot項目多層級多環(huán)境yml設(shè)計詳解
這篇文章主要為大家介紹了SpringBoot項目多層級多環(huán)境yml設(shè)計詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03java中MultipartFile類型轉(zhuǎn)為File類型的4種方法
Spring提供了一個MultipartFile接口來處理文件上傳,但有時候我們需要將MultipartFile轉(zhuǎn)換為File來進(jìn)行一些特定的操作,比如保存文件到本地或者進(jìn)行文件的處理等,這篇文章主要給大家介紹了關(guān)于java中MultipartFile類型轉(zhuǎn)為File類型的4種方法,需要的朋友可以參考下2024-09-09application作用域?qū)崿F(xiàn)用戶登錄擠掉之前登錄用戶代碼
這篇文章主要介紹了application作用域?qū)崿F(xiàn)用戶登錄擠掉之前登錄用戶代碼,具有一定參考價值,需要的朋友可以了解下。2017-11-11Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運行
這篇文章主要介紹了Java并發(fā)編程示例(七):守護(hù)線程的創(chuàng)建和運行,在本節(jié)示例中,我們將創(chuàng)建兩個線程,一個是普通線程,向隊列中寫入事件,另外一個是守護(hù)線程,清除隊列中的事件,需要的朋友可以參考下2014-12-12