Java中Volatile怎么用

這篇文章將為大家詳細(xì)講解有關(guān)Java中Volatile怎么用,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)公司專注于鐵鋒網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠(chéng)為您提供鐵鋒營(yíng)銷型網(wǎng)站建設(shè),鐵鋒網(wǎng)站制作、鐵鋒網(wǎng)頁(yè)設(shè)計(jì)、鐵鋒網(wǎng)站官網(wǎng)定制、小程序開(kāi)發(fā)服務(wù),打造鐵鋒網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供鐵鋒網(wǎng)站排名全網(wǎng)營(yíng)銷落地服務(wù)。

 Volatile:

volatile同步機(jī)制又涉及Java內(nèi)存模型中的可見(jiàn)性、原子性和有序性,惡補(bǔ)基礎(chǔ)一波。

可見(jiàn)性:

可見(jiàn)性簡(jiǎn)單的說(shuō)是線程之間的可見(jiàn)性,一個(gè)線程修改的狀態(tài)對(duì)另一個(gè)線程是可見(jiàn)對(duì),也就是一個(gè)線程的修改結(jié)果另一個(gè)線程可以馬上看到;但通常,我們無(wú)法確保執(zhí)行讀操作的線程能夠時(shí)時(shí)的看到其他線程寫(xiě)入的值,So為了確保多個(gè)線程之間對(duì)內(nèi)存寫(xiě)入操作可見(jiàn)性,必須使用同步機(jī)制;如用volatile修飾的變量就具有可見(jiàn)性,volatile修飾的變量不允許線程內(nèi)部緩存和重排序,而是直接修改內(nèi)存,所以對(duì)其他線程來(lái)說(shuō)是可見(jiàn)的;但volatile只能保證被修飾的內(nèi)容具有可見(jiàn)性,并不具備原子性,如volatile int vipNumber = 100,之后有一個(gè)vipNumber++ 的操作,這個(gè)變量vipNumber具有可見(jiàn)性,但是vipNumber++ 依然是一個(gè)非原子操作,也就是說(shuō)這個(gè)操作同樣存在線程安全問(wèn)題。

原子性:

原子具有不可分割的特性,如int age = 22,這個(gè)操作是不可分割的,那么稱其為原子操作,具有原子性;再比如age++,這個(gè)操作實(shí)際是age = age + 1,其是可分割的,So它不是一個(gè)原子操作;而非原子操作都會(huì)存在線程安全問(wèn)題,需要我們使用同步技術(shù)(synchronized)來(lái)讓它變成一個(gè)原子操作;Java的concurrent包下提供了一些原子類,如:AtomicLongMap、AtomicDouble、AtomicReference 等;在Java中用synchronized、lock和unlock來(lái)保證原子性。

有序性:

Java語(yǔ)言提供了volatile和synchronized兩個(gè)關(guān)鍵字來(lái)保證線程之間操作的有序性,volatile是因?yàn)楸旧戆敖怪噶钪嘏判颉钡恼Z(yǔ)義,synchronized是由“一個(gè)變量在同一時(shí)刻只允許一條線程對(duì)其進(jìn)行l(wèi)ock操作”這條規(guī)則獲得有序性的,此規(guī)則決定了持有同一個(gè)對(duì)象鎖的兩個(gè)同步塊只能串行執(zhí)行。

Volatile原理:

volatile是一種稍弱的同步機(jī)制,其用來(lái)確保將變量的更新操作通知到其他線程;當(dāng)變量聲明為volatile類型后,編譯器與JVM運(yùn)行時(shí)都會(huì)注意到這個(gè)變量時(shí)共享的,因此不會(huì)將此變量上的操作與其他操作一起重排序;volatile修飾后變量不會(huì)緩存在寄存器或者對(duì)其他處理器不可見(jiàn)的地方,因此在單曲volatile類型的變量時(shí)總會(huì)返回最新寫(xiě)入的值;除此之外,在訪問(wèn)volatile變量時(shí)不會(huì)執(zhí)行加鎖操作,也就不會(huì)執(zhí)行線程阻塞,因此volatile變量是一種比synchronized關(guān)鍵字更輕量級(jí)的同步機(jī)制;當(dāng)對(duì)非volatile變量進(jìn)行讀寫(xiě)時(shí),每個(gè)線程從內(nèi)存拷貝變量到CPU緩存中,如果計(jì)算機(jī)有多個(gè)CPU則每個(gè)線程可能在不同的CPU上被處理,這就意味著每個(gè)線程都可以拷貝到不同的CPU緩存cache中,而不是像volatile變量那樣直接讀內(nèi)存,JVM保證其每次讀變量都從內(nèi)存中讀,跳過(guò)了CPU cache這一步驟。

當(dāng)一個(gè)變量定義為volatile之后,其具備的兩種特征:

1、保證此變量對(duì)所有的線程的可見(jiàn)性;當(dāng)一個(gè)線程修改了此變量的值,volatle保證新值能夠立即同步到主內(nèi)存,以及每次使用前立即從主每次刷新;

2、禁止指令重排序優(yōu)化;被volatile修飾的變量賦值后多執(zhí)行了一個(gè)“l(fā)oad”操作,此操作相當(dāng)于一個(gè)內(nèi)存屏障(指令重排序時(shí)不能把后面的指令重排序到內(nèi)存屏障之前到位置),只有一個(gè)CPU訪問(wèn)內(nèi)存時(shí),不需要內(nèi)存屏障;(指令重排序:指CPU采用了允許將多條指令不按程序規(guī)定的順序分開(kāi)發(fā)送給各相應(yīng)電路單元處理)

另外:在性能方面,volatile的讀操作性能消耗與普通變量基本無(wú)異,但是寫(xiě)操作稍慢,因?yàn)樗枰诒镜卮a中插入許多內(nèi)存屏障來(lái)保證處理器不發(fā)生亂序執(zhí)行。

這里擼了一個(gè)例子用volatile保證線程間的同步,如果變量author不經(jīng)volatile修飾,線程2中對(duì)author的值做了修改并未同步到線程1中,其一直存在緩存中。

Java中Volatile怎么用

FYI:

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class TestVolatile {
 //private volatile String author = "tjt"; // volatile修飾author保證兩個(gè)線程到可見(jiàn)性,即不存在緩存cache中
 private String author = "tjt"; // 不用volatile修飾變量author則author修改值后在線程之間并不可見(jiàn)
 private boolean enable = false;
 public static void main(String[] args) throws Exception {
  TestVolatile testVolatile = new TestVolatile();
  log.info("原始定義的author: "+testVolatile.author);
  Thread thread = new Thread( new Runnable() {
   @Override
   public void run() {
    testVolatile.testMethodOne();
   }
  });
  thread.start();
  thread.sleep(2000l);
  testVolatile.testMethodTwo();
 }
 public void testMethodOne() {
  while(true) {
   if ("detect_tjt".equals(author) && enable == false) {
    log.info("線程testMethodOne中檢測(cè)到來(lái)author修改為: "+author);
    enable = true;
    System.exit(0);
   }
  }  }
 public void testMethodTwo() {
  author = "detect_tjt";
  log.info("線程testMethodTwo中把a(bǔ)uthor修改為: "+author);
 }
}

用volatile修飾author執(zhí)行結(jié)果:
- 原始定義的author: tjt
- 線程testMethodTwo中把a(bǔ)uthor修改為: detect_tjt
- 線程testMethodOne中檢測(cè)到來(lái)author修改為: detect_tjt
無(wú)volatile修飾author執(zhí)行結(jié)果:

- 原始定義的author: tjt
- 線程testMethodTwo中把a(bǔ)uthor修改為: detect_tjt

關(guān)于“Java中Volatile怎么用”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

本文名稱:Java中Volatile怎么用
新聞來(lái)源:http://muchs.cn/article20/jogijo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開(kāi)發(fā)、企業(yè)建站、微信公眾號(hào)、云服務(wù)器定制開(kāi)發(fā)、網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作