摘要:貓說多線程之內存可見性下篇歡迎你留言討論屬于你的見解,畢竟每個人的味蕾都不一樣,這杯咖啡有吸引到你嗎好像又是一個槽糕的比喻本文已轉載個人技術公眾號歡迎留言討論與點贊上一篇推薦貓說主數據類型和引用下一篇推薦貓說多線程之內存可見性下篇
閱讀本文約“3分鐘”
本文大致講述兩種線程實現的可見性,或許你已經提前想到了,那說明你的基礎很好,我們要聊聊synchronized實現可見性與volatile實現可見性。
我們會談及幾個點:指令重排序、as-if-serial語義、volatile使用注意事項等
首先我們要了解下兩個名詞,有點術語的感覺,雖然我不喜歡那些專業名詞,但是你懂得···
可見性:通俗的說就是一個線程對共享變量值的修改,可以及時地被其它線程看到
共享變量:即一個變量在多個線程的工作內存中存在副本,則這個變量就是這些線程的共享變量
這兩個名稱理解起來還不算難,對吧?那么我們來看看更加專業化的名詞,我其實更希望有具象化的有趣的名詞來代替,原諒我的文學水平有限。
Java內存模型(JMM)
Java Memory Model 描述了Java程序中各種變量(這里指線程共享變量,你已經理解上面的第二個名詞了)的訪問規則,以及在JVM中將變量存儲到內存和從內存中讀取出變量這樣的底層細節,就像細胞要在血管中流動一樣(一個不及格的比喻),它要求所有的變量都存儲在主內存中,每個線程都有自己獨立的工作內存,里面保存該線程使用到的變量的副本(也就是主內存中該變量的一份拷貝)
讓我們來看看圖型吧,文字有時理解起來比起圖片要來的復雜,至少我是這樣覺得,我更喜歡具象化的說明
對于色調我一直有不同于別人的理解,原諒我看似混亂的搭配。
綜合的總結一下,結合上圖還有之前說的,我們可以定出一下兩個原則(或許可以輕松一點的說,而不是用“原則”)
1、線程對共享變量的所有操作都必須在自己的工作空間(內存)中進行,不能直接從主內存中讀寫
2、不同線程之間無法直接訪問其他線程中工作內存中的變量,線程間的變量值的傳遞需要通過主內存來完成
以上兩句可能需要細細體會,就像你喝咖啡后不會立馬喝下一口一樣,請回味一下。
由此我們可以模糊但又明確的指出共享變量可見性實現的原理
結合下圖一同說明下,線程A對共享變量的修改要想被線程B即使看到,需要經過如下兩步:
1、把工作內存A中更新過的共享變量刷新到主內存中
2、將主內存中最新的共享變量的值更新到工作內存B中
讓我們重新回到主題,Java語言層面支持的可見性實現方式:
——synchronized
——volatile
而由以上的篇幅講解你也知道了實現共享變量的可見性,需要保證兩點:
1、線程修改后的共享變量值能夠及時從其工作內存中刷新到主內存中
2、其他線程能夠及時把共享變量的最新值從主內存更新到自己的工作內存中
synchronized可以實現在于它的性質:原子性(同步性)、可見性
JMM(看到這個單詞時或許你應該想到前面的中文含義)關于synchronized有這樣的一些規定:
1、線程解鎖前,必須把共享變量的最新值刷新到主內存中
2、線程加鎖時,將清空工作內存中共享變量的值,在使用共享變量時需要從主內存中重新讀取最新的值
(需要注意的是,加鎖與解鎖需要同一把鎖,這讓我想到了Redis,你想到了什么呢?)
我們可精華的提升下,即線程解鎖前對共享變量的修改在下次加鎖時對其他線程是可見的
讓我們大致看看線程執行互斥代碼(即以上的描述)的過程:
1、獲得互斥鎖
2、清空工作內存
3、從主內存拷貝變量的最新副本到工作內存
4、執行代碼
5、將更改后的共享變量的值刷新到主內存
6、釋放互斥鎖
(請自己思考一次,不要把5、6步的順序顛倒了哦)
本文未完~,請期待下篇。
【Java貓說】Java多線程之內存可見性(下篇)
歡迎你留言討論屬于你的見解,畢竟每個人的味蕾都不一樣,這杯咖啡有吸引到你嗎?
(好像又是一個槽糕的比喻)
本文已轉載個人技術公眾號:UncleCatMySelf
歡迎留言討論與點贊
上一篇推薦:【Java貓說】主數據類型和引用
下一篇推薦:【Java貓說】Java多線程之內存可見性(下篇)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71652.html
摘要:閱讀本文約分鐘上一次我們說到互斥代碼的實現過程,如果有忘記或不清楚的可以去上篇看看。貓說多線程之內存可見性上篇今天我們了解下重排序。 閱讀本文約3分鐘 上一次我們說到synchronized互斥代碼的實現過程,如果有忘記或不清楚的可以去上篇看看?!綣ava貓說】Java多線程之內存可見性(上篇) 今天我們了解下重排序。 其使代碼書寫的順序與實現執行的順序不同,指令重排序是編譯器或處理...
摘要:閱讀本文約分鐘變量有兩種主數據類型和引用。主數據類型用來保存基本類型的值,包括整數,布爾和浮點數等,而對象引用保存的是對象的引用。而在中,主數據類型也有不用的大小與名稱。 閱讀本文約2.3分鐘 變量有兩種:primitive主數據類型和引用。 Java注重類型。它不會讓你做出把長頸鹿類型變量裝進兔子類型變量中這種詭異又危險的舉動——如果有人對長頸鹿調用跳躍這個方法會發生什么悲?。坎⑶?..
摘要:閱讀本文約分鐘對象的行為,這里的對象即上一章中的類吧淺意狀態影響行為,行為影響狀態這是一個令人深思的話題了。是通過值傳遞的,也就是說通過拷貝傳遞。聲明一個類型的變量并賦值為,代表的字節組合會放進稱為的變量中。 閱讀本文約2分鐘 對象的行為,這里的對象即上一章中的類吧(淺意) 狀態影響行為,行為影響狀態! 這是一個令人深思的話題了。 同一類型的每個對象能夠有不同的方法行為嗎? 仔細想一...
閱讀 986·2021-09-26 10:15
閱讀 2064·2021-09-24 10:37
閱讀 2580·2019-08-30 13:46
閱讀 2631·2019-08-30 11:16
閱讀 2421·2019-08-29 10:56
閱讀 2591·2019-08-26 12:24
閱讀 3472·2019-08-23 18:26
閱讀 2662·2019-08-23 15:43