Java中的關(guān)鍵字volatile詳解
volatile關(guān)鍵字經(jīng)常用來修飾變量。不過,volatile本身很容易被誤用。本篇就介紹一下volatile的原理和使用方式。
在介紹volatile關(guān)鍵字原理前,我們首先要了解JVM運行時的內(nèi)存分配邏輯。
對于成員變量i,它存儲在堆內(nèi)存中。每個線程在運行時都會有一個自己的線程棧,線程如果要訪問類的成員變量i,會通過引用獲取到堆中變量i實際的值10,然后把這個變量值拷貝到自己的棧內(nèi)存中,作為一個變量副本,之后線程便不再會與堆中的變量有實際聯(lián)系。每個線程都有一個自己的本地副本,相互隔離。線程訪問自己棧內(nèi)存的效率比訪問堆的效率高。線程對變量i值的修改,只會修改自己線程副本中的值,修改結(jié)束后,在線程退出前,會把自己線程副本中的值,刷新到堆中。
保證內(nèi)存可見性
對于如下代碼:
public class VolatileTest implements Runnable{ //volatile private static boolean flag = false; @Override public void run() { while (!flag){ System.out.println(Thread.currentThread().getName() +"執(zhí)行中"); } System.out.println(Thread.currentThread().getName() +"執(zhí)行完畢"); } //main線程 public static void main(String[] args) throws InterruptedException { new Thread(new VolatileTest(), "支線程Volatile").start(); Thread.sleep(1000); flag = true; } }
大多數(shù)時候可以正常中斷,但是一旦發(fā)送異常,便會導(dǎo)致線程死循環(huán)。所以需要在flag標志上加一個volatile關(guān)鍵字。對于加了volatile關(guān)鍵字的變量值,線程1修改了這個值的話,會強制將修改值直接寫入堆內(nèi)存中,其他線程各自線程棧中的變量副本無效,只能去堆中取最新的變量值。多個線程之間的內(nèi)存可見得以保證。
值得注意的是,volatile關(guān)鍵字不能保證原子性。
private volatile int i; i++;
i ++ 這個操作涉及到獲取值,自增和賦值3部分。無法直接完成。上面想要以volatile來實現(xiàn)原子性的寫法是錯誤的。
禁止指令重排
現(xiàn)代JVM對代碼的執(zhí)行順序有一定的優(yōu)化。例如:
int a = 4; int b = 5; int c = a + b;
上面3條指令進過JVM優(yōu)化以后,時間的執(zhí)行順序不一定是從上到下,有可能是 第二條--->第一條-->第三條??傊粫绊懽罱K執(zhí)行結(jié)果。
但是在多線程情況下,如下代碼就會有風(fēng)險:
//線程1: context = loadContext(); inited = true; //線程2: while(!inited ){ } doSomething(context);
線程1的兩條語句之間沒有依賴性,經(jīng)過指令重排后,有可能inited置為true以后,context還沒有初始化。線程2發(fā)現(xiàn)inited為true,以為初始化完成,結(jié)束循環(huán),用時間還沒有初始化的context去執(zhí)行doSomething()方法。報錯。所以我們可以用volatile關(guān)鍵字修飾inited,保證context初始化。
以上所述是小編給大家介紹的Java中的關(guān)鍵字volatile詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
- Java并發(fā)編程volatile關(guān)鍵字的作用
- Java多線程并發(fā)編程 Volatile關(guān)鍵字
- Java并發(fā)編程:volatile關(guān)鍵字詳細解析
- 詳細分析java并發(fā)之volatile關(guān)鍵字
- 深入了解Java中Volatile關(guān)鍵字
- Java Volatile關(guān)鍵字同步機制詳解
- Java Volatile關(guān)鍵字實現(xiàn)原理過程解析
- 簡單了解java volatile關(guān)鍵字實現(xiàn)的原理
- 一文精通Java中的volatile關(guān)鍵字
- Java面試官最喜歡問的關(guān)鍵字之volatile詳解
- 詳解Java面試官最愛問的volatile關(guān)鍵字
- Java中Volatile關(guān)鍵字詳解及代碼示例
- Java并發(fā)編程——volatile關(guān)鍵字
相關(guān)文章
Java中對象的深復(fù)制(深克?。┖蜏\復(fù)制(淺克隆)介紹
這篇文章主要介紹了Java中對象的深復(fù)制(深克?。┖蜏\復(fù)制(淺克?。?,需要的朋友可以參考下2015-03-03mybatis+springboot發(fā)布postgresql數(shù)據(jù)的實現(xiàn)
本文主要介紹了mybatis+springboot發(fā)布postgresql數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-11-11Spring Data JPA使用JPQL與原生SQL進行查詢的操作
這篇文章主要介紹了Spring Data JPA使用JPQL與原生SQL進行查詢的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Spring Cloud 專題之Sleuth 服務(wù)跟蹤實現(xiàn)方法
這篇文章主要介紹了Spring Cloud 專題之Sleuth 服務(wù)跟蹤,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08multi-catch和try-catch異常處理知識點詳解
在本篇文章里我們給大家分享了一篇關(guān)于multi-catch和try-catch異常處理知識點內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。2019-11-11