日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java中的Volatile关键字使用

發(fā)布時(shí)間:2024/2/28 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java中的Volatile关键字使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • 什么時(shí)候使用volatile
    • Happens-Before

java中的Volatile關(guān)鍵字使用

在本文中,我們會(huì)介紹java中的一個(gè)關(guān)鍵字volatile。 volatile的中文意思是易揮發(fā)的,不穩(wěn)定的。那么在java中使用是什么意思呢?

我們知道,在java中,每個(gè)線程都會(huì)有個(gè)自己的內(nèi)存空間,我們稱之為working memory。這個(gè)空間會(huì)緩存一些變量的信息,從而提升程序的性能。當(dāng)執(zhí)行完某個(gè)操作之后,thread會(huì)將更新后的變量更新到主緩存中,以供其他線程讀寫。

因?yàn)樽兞看嬖趙orking memory和main memory兩個(gè)地方,那么就有可能出現(xiàn)不一致的情況。 那么我們就可以使用Volatile關(guān)鍵字來(lái)強(qiáng)制將變量直接寫到main memory,從而保證了不同線程讀寫到的是同一個(gè)變量。

什么時(shí)候使用volatile

那么我們什么時(shí)候使用volatile呢?當(dāng)一個(gè)線程需要立刻讀取到另外一個(gè)線程修改的變量值的時(shí)候,我們就可以使用volatile。我們來(lái)舉個(gè)例子:

public class VolatileWithoutUsage {private int count = 0;public void incrementCount() {count++;}public int getCount() {return count;} }

這個(gè)類定義了一個(gè)incrementCount()方法,會(huì)去更新count值,我們接下來(lái)在多線程環(huán)境中去測(cè)試這個(gè)方法:

@Testpublic void testWithoutVolatile() throws InterruptedException {ExecutorService service= Executors.newFixedThreadPool(3);VolatileWithoutUsage volatileWithoutUsage=new VolatileWithoutUsage();IntStream.range(0,1000).forEach(count ->service.submit(volatileWithoutUsage::incrementCount) );service.shutdown();service.awaitTermination(1000, TimeUnit.MILLISECONDS);assertEquals(1000,volatileWithoutUsage.getCount() );}

運(yùn)行一下,我們會(huì)發(fā)現(xiàn)結(jié)果是不等于1000的。

java.lang.AssertionError: Expected :1000 Actual :999

這是因?yàn)槎嗑€程去更新同一個(gè)變量,我們?cè)谏掀恼乱蔡岬搅?#xff0c;這種情況可以通過(guò)加Synchronized關(guān)鍵字來(lái)解決。

那么是不是我們加上Volatile關(guān)鍵字后就可以解決這個(gè)問(wèn)題了呢?

public class VolatileFalseUsage {private volatile int count = 0;public void incrementCount() {count++;}public int getCount() {return count;}}

上面的類中,我們加上了關(guān)鍵字Volatile,我們?cè)贉y(cè)試一下:

@Testpublic void testWithVolatileFalseUsage() throws InterruptedException {ExecutorService service= Executors.newFixedThreadPool(3);VolatileFalseUsage volatileFalseUsage=new VolatileFalseUsage();IntStream.range(0,1000).forEach(count ->service.submit(volatileFalseUsage::incrementCount) );service.shutdown();service.awaitTermination(5000, TimeUnit.MILLISECONDS);assertEquals(1000,volatileFalseUsage.getCount() );}

運(yùn)行一下,我們會(huì)發(fā)現(xiàn)結(jié)果還是錯(cuò)誤的:

java.lang.AssertionError: Expected :1000 Actual :992 ~~為什么呢? 我們先來(lái)看下count++的操作,count++可以分解為三步操作,1. 讀取count的值,2.給count加1, 3.將count寫回內(nèi)存。添加Volatile關(guān)鍵詞只能夠保證count的變化立馬可見(jiàn),而不能保證1,2,3這三個(gè)步驟的總體原子性。 要實(shí)現(xiàn)總體的原子性還是需要用到類似Synchronized的關(guān)鍵字。下面看下正確的用法:~~~java public class VolatileTrueUsage {private volatile int count = 0;public void setCount(int number) {count=number;}public int getCount() {return count;} } @Testpublic void testWithVolatileTrueUsage() throws InterruptedException {VolatileTrueUsage volatileTrueUsage=new VolatileTrueUsage();Thread threadA = new Thread(()->volatileTrueUsage.setCount(10));threadA.start();Thread.sleep(100);Thread reader = new Thread(() -> {int valueReadByThread = volatileTrueUsage.getCount();assertEquals(10, valueReadByThread);});reader.start();}

Happens-Before

從java5之后,volatile提供了一個(gè)Happens-Before的功能。Happens-Before 是指當(dāng)volatile進(jìn)行寫回主內(nèi)存的操作時(shí),會(huì)將之前的非volatile的操作一并寫回主內(nèi)存。

public class VolatileHappenBeforeUsage {int a = 0;volatile boolean flag = false;public void writer() {a = 1; // 1 線程A修改共享變量flag = true; // 2 線程A寫volatile變量} }

上面的例子中,a是一個(gè)非volatile變量,flag是一個(gè)volatile變量,但是由于happens-before的特性,a 將會(huì)表現(xiàn)的和volatile一樣。

本文的例子可以參考:https://github.com/ddean2009/learn-java-concurrency/tree/master/volatile

更多精彩內(nèi)容且看:

  • 區(qū)塊鏈從入門到放棄系列教程-涵蓋密碼學(xué),超級(jí)賬本,以太坊,Libra,比特幣等持續(xù)更新
  • Spring Boot 2.X系列教程:七天從無(wú)到有掌握Spring Boot-持續(xù)更新
  • Spring 5.X系列教程:滿足你對(duì)Spring5的一切想象-持續(xù)更新
  • java程序員從小工到專家成神之路(2020版)-持續(xù)更新中,附詳細(xì)文章教程

更多教程請(qǐng)參考 flydean的博客

總結(jié)

以上是生活随笔為你收集整理的java中的Volatile关键字使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。