Java中的volatile關(guān)鍵字解析
volatile關(guān)鍵字
在對(duì)該關(guān)鍵字進(jìn)行認(rèn)識(shí)之前,需要對(duì)Java內(nèi)存模型有一定的認(rèn)識(shí)。 Java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存中,每個(gè)線程都有自己的工作內(nèi)存,線程的工作內(nèi)存保存了該線程使用到的變量的是主內(nèi)存副本的拷貝,線程對(duì)于變量的操作(讀取,復(fù)制)都必須在工作內(nèi)存中進(jìn)行,而不能直接讀寫主內(nèi)存中的變量。
在進(jìn)行變量操作的時(shí)候,如果每次都是從主內(nèi)存中讀寫,無疑是影響性能的, 即一個(gè)線程在操作某一個(gè)變量之前,會(huì)先把變量的值從主內(nèi)存中拷貝一個(gè)副本放到工作內(nèi)存中,操作完成之后同步到主內(nèi)存中。不同的線程之間無法直接訪問對(duì)方工作內(nèi)存中的變量,線程間變量值的傳遞均需要通過主內(nèi)存來完成。
volatile: 當(dāng)一個(gè)變量被定義為volatile(不穩(wěn)定的)之后,線程在進(jìn)行變量操作的時(shí)候,都不會(huì)使用本地內(nèi)存中之前緩存的數(shù)據(jù),而是每次都會(huì)從主內(nèi)存中把變量的值拷貝副本到工作內(nèi)存中,這樣就保證了變量對(duì)于所有線程的可見性。
public class TestVolatile { public static void main(String[] args) throws Exception { ThreadDemo td=new ThreadDemo(); Thread t=new Thread(td); t.start(); while(true){ if(td.isFlag()){ System.out.println("OK"); break; } } } } class ThreadDemo implements Runnable{ private volatile boolean flag=false; @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } flag=true; System.out.println("flag="+isFlag()); } public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } }
需要特別注意的是, 即使volatile能夠保證其變量對(duì)于線程的可見性,但是卻不能保證并發(fā)的安全性。
比如多線程執(zhí)行線程執(zhí)行i++(i假設(shè)用volatilex修飾)也不能保證其安全性。 如下圖:
因?yàn)閕++并不是原子性的操作,當(dāng)一個(gè)線程A再工作內(nèi)存中進(jìn)行數(shù)據(jù)操作的時(shí)候,還未結(jié)束的時(shí)候,cpu切換到了另一個(gè)線程B,而此時(shí)之前i++操作并沒有結(jié)束,即并沒有把數(shù)據(jù)刷新到主內(nèi)存中,此時(shí)B獲取到的數(shù)據(jù)跟A獲取的數(shù)據(jù)實(shí)際上是一樣的,這時(shí)候就存在了并發(fā)的問題了。
到此這篇關(guān)于Java中的volatile關(guān)鍵字解析的文章就介紹到這了,更多相關(guān)Java中的volatile內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?AOP?后置通知修改響應(yīng)httpstatus方式
這篇文章主要介紹了Spring?AOP?后置通知修改響應(yīng)httpstatus方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Maven構(gòu)建SpringBoot集成MyBatis過程
文章介紹了如何使用Maven創(chuàng)建一個(gè)Spring Boot項(xiàng)目,并集成MyBatis,首先,配置Maven環(huán)境,然后在pom.xml中添加MyBatis依賴,配置數(shù)據(jù)庫連接信息,最后生成Mapper XML文件和DAO層代碼2024-11-11Spring Boot加密配置文件特殊內(nèi)容的示例代碼詳解
這篇文章主要介紹了Spring Boot加密配置文件特殊內(nèi)容的相關(guān)知識(shí),本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05SpringBoot+ECharts是如何實(shí)現(xiàn)數(shù)據(jù)可視化的
今天帶大家學(xué)習(xí)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著SpringBoot+ECharts怎么實(shí)現(xiàn)數(shù)據(jù)可視化展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06Jackson java動(dòng)態(tài)去除返回json中的值方式
文章介紹了在Java中使用@JsonInclude注解動(dòng)態(tài)去除返回JSON中的非必需字段(如分頁信息)的解決方案,通過在字段上添加@JsonInclude注解并選擇合適的策略(如NON_NULL或NON_EMPTY),可以在非分頁情況下取消分頁字段,從而提高返回結(jié)果的靈活性和效率2024-12-12基于Java SWFTools實(shí)現(xiàn)把pdf轉(zhuǎn)成swf
這篇文章主要介紹了基于Java SWFTools實(shí)現(xiàn)把pdf轉(zhuǎn)成swf,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11