日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Java并发编程-volatile关键字介绍

發布時間:2023/12/15 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java并发编程-volatile关键字介绍 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

要學習好Java的多線程,就一定得對volatile關鍵字的作用機制了熟于胸。最近博主看了大量關于volatile的相關博客,對其有了一點初步的理解和認識,下面通過自己的話敘述整理一遍。

有什么用?

volatile主要對所修飾的變量提供兩個功能

  • 可見性
  • 防止指令重排序


本篇博客主要對volatile可見性進行探討,以后發表關于指令重排序的博文。

什么是可見性?

一圖勝千言

上圖已經把JAVA內存模型(JMM)展示得很詳細了,簡單概括一下

  • 每個Thread有一個屬于自己的工作內存(可以理解為每個廚師有一個屬于自己的鐵鍋)
  • 所有Thread共用一個主內存(餐廳所有的廚師共用同一個冰箱)
  • 每個Thread操作數據之前都會去主內存中獲取數據(廚師炒菜之前都要去冰箱里拿食材)
    • Thread:廚師
    • 工作內存:鐵鍋
    • store&load:放熟食,取食材
    • 主內存:冰箱

    讀者可思考以下情景:

    餐廳來了一位顧客點了一份紅燒肉,此時有兩位大廚(假設大廚之間互不通信),由于互不通信,所以兩位大廚都打開冰箱取出食材開始炒菜。
    最后炒出了兩份紅燒肉,顧客只要一份。為什么會造成這種結果?

    由于大廚之間沒有可見性。

    將此情景放在JAVA中即是:

    線程A從主內存中取了一個變量到工作內存中,操作完畢后沒有及時放回主內存中,于是線程B去取這個變量已經過期了,取的是線程A操作之前的變量。

    如何擁有可見性?

    先介紹一下Java內存模型中定義的8種工作內存與主內存之間的原子操作

    • lock( 鎖定 ):作用于主內存的變量,把一個變量標識為一條線程獨占的狀態。
    • unlock(解鎖):作用于主內存的變量,把一個處于鎖定的變量釋放出來,釋放變量才可以被其他線程鎖定。
    • read(讀取):作用于主內存的變量,把一個變量的值從主內存傳輸到線程的工作內存中,以便隨后的load動作使用。
    • load(載入):作用于工作內存的變量,它把read操作從主內存中得到的變量值放入工作內存的變量副本中。
    • use(使用):作用于工作內存種的變量,它把工作內存中一個變量的值傳遞給執行引擎,每當虛擬機遇到一個需要使用到變量的值的字節碼指令時將會執行這個操作。
    • assign(賦值):作用于工作內存中的變量,它把一個從執行引擎接收到的值賦給工作內存的變量,每當虛擬機遇到一個給變量賦值的字節碼指令時執行這個操作。
    • store(存儲):作用于工作內存的變量,它把工作內存中一個變量的值傳送到主內存中,以便隨后的write操作使用
    • write(寫入):作用于主內存的變量,它把store操作從工作內存中得到的值放入主內存的變量中。
    讀取賦值一個普通變量的情況


    當線程1對主內存對象發起read操作到write操作套流程的時間里,線程2隨時都有可能對這個主內存對象發起第二套操作

    • 有什么危害呢?

    假設主內存中有一個

    int a=0;

    線程1和線程2分別執行一次,理想狀態下最終a的值為2.

    a++;

    線程1在執行了assign操作之后變量a的真實值已經從0變成了1,但是這個過程發生在工作內存中對其他線程不可見,若線程2此時對變量a的操作,讀取到的值仍然為0,因為沒有可見性,線程2的操作也僅僅是重復了線程1的操作,再次讓a從0變成了1。并沒有達到期望的a=2。

    讀取賦值一個volatile變量的情況


    volatile變量對對象的操作更嚴格:

    • use之前不能被read&load
    • assign之后必須緊跟store&write

    也就是說 read-load-useassign-store-write成為了兩個不可分割的原子操作

    盡管這時候在use和assign之間依然有一段真空期,有可能變量會被其他線程讀取,但是無論在哪一個時間點主內存的變量和任一工作內存的變量的值都是相等的。這個特性就導致了volatile變量不適合參與到依賴當前值的運算,如自增。
    那么依靠可見性的特點volatile可以用在哪些地方呢?
    《Java虛擬機》提到:

    運算結果并不依賴變量的當前值(即結果對產生中間結果不依賴),或者能夠確保只有單一的線程修改變量的值

    通常volatile用做保存某個狀態的boolean值。


    部分參考自

    • volatile變量與普通變量的區別
    • <<深入理解Java虛擬機 高級特性與最佳實踐>>

    總結

    以上是生活随笔為你收集整理的Java并发编程-volatile关键字介绍的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。