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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 线程由浅入深_Java多线程:由浅入深看synchronized的底层实现原理

發布時間:2024/7/23 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 线程由浅入深_Java多线程:由浅入深看synchronized的底层实现原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java多線程:由淺入深看synchronized的底層實現原理-1.jpg (91.72 KB, 下載次數: 0)

2018-9-21 03:55 上傳

前言

前倆篇文章,我們聊了聊線程/進程的概念,接著簡單串了一下同步的體例體例。今天我們就單拎出來synchronized,好好捋一捋它的前世今生。

正文

小A:咱們前幾天鋪墊了這么多內容,今天是不是要好好的深挖一下原理的內容了?

MDove:沒錯,接下來。我會從常見的synchronized加鎖體例入手;引出Java對象在內存的結構,以及鎖的寄存位置;然后看一看鎖在C++中的簡單實現思路;最后咱們從字節碼中,看一下JVM如果識別synchronized。內容不是很難,不會涉及到特別多深奧的內容,大部分是平鋪直敘的介紹,很適合閱讀呦~

小A:快點開始吧,我等不及啦。

淺聊synchronized的使用

MDove:說起synchronized的底層實現原來,咱們先看看synchronized的倆種加鎖體例:

1、某個對象實例內

此作用域內的synchronized鎖 ,可以避免多個線程同時拜候這個對象的synchronized體例

并且一個對象有多個synchronized體例,只要一個線程拜候了其中的一個synchronized體例,其它線程不克不及同時拜候這個對象中任何一個synchronized體例。

另外,不合對象實例的synchronized體例是不相干涉干與的。也就是說,其它線程可以同時拜候此類下的另一個對象實例中的synchronized體例;

Java多線程:由淺入深看synchronized的底層實現原理-2.jpg (12.36 KB, 下載次數: 0)

2018-9-21 03:55 上傳

2、某個類

此作用域下,可以避免多個線程同時拜候這個類中的synchronized體例。也就是說此種修飾,可以對此類的所有對象實例起作用。

Java多線程:由淺入深看synchronized的底層實現原理-3.jpg (12.71 KB, 下載次數: 0)

2018-9-21 03:55 上傳

MDove:注意一點,synchronized關鍵字是不克不及繼承的,也就是說,基類的體例synchronized fun(){} 在繼承類中其實不自動是synchronized fun(){},而是釀成了fun(){}。繼承時,需要顯式的指定它的某個體例為synchronized體例。有機會你可以自己寫個demo試一下。

常見毛病

MDove:你來看一看下面這個demo,有沒有什么問題?

Java多線程:由淺入深看synchronized的底層實現原理-4.jpg (21.35 KB, 下載次數: 0)

2018-9-21 03:55 上傳

小A:沒覺得有問題吶?這不就是第一種加鎖的體例,鎖實例對象么?

MDove:既然你都知道是鎖實例對象,那你沒看出來問題么?雖然我們使用synchronized修飾了add()。可是卻new了兩個不合的實例對象,這也就意味著存在著兩個不合的實例對象鎖,因此t1和t2城市進入各自的對象鎖,也就是說t1和t2線程使用的是不合的鎖,因此線程平安是無法包管的。

小A:對對對,沒錯。那解決這種問題,是不是需要用第二種加鎖的體例,鎖住這個類?

MDove:沒錯,解決這種困境的的體例是將synchronized作用于靜態的add體例,這樣的話,對象鎖就當前類,因為類對象只有一個,因此無論new幾多個實例對象都是平安的:

小A:那是不是這樣改寫就可以了?

Java多線程:由淺入深看synchronized的底層實現原理-5.jpg (7.54 KB, 下載次數: 0)

2018-9-21 03:55 上傳

MDove:沒錯就是這樣,很簡單。接下來讓我們看一些深入的內容,鎖的實現。

synchronized鎖的底層實現

MDove:我們都知道,對象被建立在堆中。并且對象在內存中的存儲結構體例可以分為3塊區域:對象頭、實例數據、對齊填充。其中對象頭,即是我們今天的主角。

Java多線程:由淺入深看synchronized的底層實現原理-6.jpg (12.49 KB, 下載次數: 0)

2018-9-21 03:55 上傳

關于實例數據、對齊填充的作用,各位小伙伴可以參考《深入理解Java虛擬機》。

MDove:對對象頭來說,主要是包含倆部分信息:

1、自身運行時的數據,好比:鎖狀態標記、線程持有的鎖…等等。(此部分內容被稱之為Mark Word)存儲內容標記位狀態 對象哈希碼、對象分代年齡 01 未鎖定 指向鎖記錄的指針 00 輕量級鎖定 指向重量級鎖的指針 10 重量級鎖定 空 11 GC標識表記標幟 偏向線程ID、偏向時間戳、對象分代年齡 01 可偏向 今天我們只聊:指向重量級鎖的指針

2、另一部分是類型指針:JVM通過這個指針來確定這個對象是哪個類的實例。

MDove:今天我們主要聊的是對象頭,第一部分中重量級鎖的內容。

MDove:先讓我們從宏觀的角度看一看synchronized鎖的實現原理。

synchronized鎖的宏觀實現

MDove:synchronized的對象鎖,其指針指向的是一個monitor對象(由C++實現)的起始地址。每個對象實例城市有一個 monitor。其中monitor可以與對象一起建立、銷毀;亦或者當線程試圖獲取對象鎖時自動生成。

monitor是由ObjectMonitor實現(ObjectMonitor.hpp文件,C++實現的),對我們來說主要關注的是如下代碼:

Java多線程:由淺入深看synchronized的底層實現原理-7.jpg (12.68 KB, 下載次數: 0)

2018-9-21 03:55 上傳

MDove:我們可以看到這里界說了_WaitSet 和 _EntryList倆個隊列,其中_WaitSet 用來保存每個期待鎖的線程對象。

小A:那_EntryList呢?

MDove:別著急,讓我們先看一下_owner,它指向持有ObjectMonitor對象的線程。當多個線程同時拜候一段同步代碼時,會先寄存到 _EntryList 集合中,接下來當線程獲取到對象的monitor時,就會把_owner變量設置為當前線程。同時count變量+1。如果線程挪用wait() 體例,就會釋放當前持有的monitor,那么_owner變量就會被置為null,同時_count減1,并且該線程進入 WaitSet集合中,期待下一次被喚醒。

MDove:固然,若當前線程順利執行完體例,也將釋放monitor,重走一遍適才的內容,也就是_owner變量就會被置為null,同時_count減1,并且該線程進入 WaitSet集合中,期待下一次被喚醒。

因為這個鎖對象寄存在對象自己,也就是為什么Java中任意對象可以作為鎖的原因。

synchronized代碼塊的底層實現

MDove:咱們先寫一個簡單的demo,然后看一下它們的字節碼:

Java多線程:由淺入深看synchronized的底層實現原理-8.jpg (9.64 KB, 下載次數: 0)

2018-9-21 03:55 上傳

Java多線程:由淺入深看synchronized的底層實現原理-9.jpg (66.46 KB, 下載次數: 0)

2018-9-21 03:55 上傳

MDove:根據虛擬機規范要求,在執行monitorenter指令時,首先要測驗考試獲取對象鎖,也就是上文我們提到了monitor對象。如果這個對象沒有被鎖定,或者當前線程已經擁有了這個對象的鎖,那么就把鎖的計數器(_count)加1。固然與之對應執行monitorexit指令時,鎖的計數器(_count)也會減1。

MDove:如果當前線程獲取鎖失敗,那么就會被阻塞住,進入_WaitSet 中,期待鎖被釋放為止。

小A:等等,我看到字節碼中,有倆個monitorexit指令,這是為什么呢?

MDove:是這樣的,編譯器需要確保體例中挪用過的每條monitorenter指令都要執行對應的monitorexit 指令。為了包管在體例異常時,monitorenter和monitorexit指令也能正常配對執行,編譯器會自動產生一個異常措置器,它的目的就是用來執行 異常的monitorexit指令。而字節碼中多出的monitorexit指令,就是異常結束時,被執行用來釋放monitor的。

小A:我們適才看的是同步代碼塊的原理,那么直接修飾在體例上呢?也是通過這個倆個指令嗎?

MDove:你別說,還真不是:

Java多線程:由淺入深看synchronized的底層實現原理-10.jpg (7.13 KB, 下載次數: 0)

2018-9-21 03:55 上傳

Java多線程:由淺入深看synchronized的底層實現原理-11.jpg (25.91 KB, 下載次數: 0)

2018-9-21 03:55 上傳

MDove:可以看到:字節碼中并沒有monitorenter指令和monitorexit指令,取得代之的是ACC_SYNCHRONIZED標識,JVM通過ACC_SYNCHRONIZED標識,就可以知道這是一個需要同步的體例,進而執行上述同步的過程,也就是_count加1,這些過程。

小A:哦,原來是這樣。一個是用了指令,一個是用的標識呀~對了,我聽說synchronized的性能特別低是這樣么?

MDove:這句話不全對,JDK1.5后對synchronized進行了大馬金刀的優化,這其中涉及到偏向鎖、輕量級鎖、自旋鎖、鎖消除等手段。時候也不早了,這些內容今天就不展開了。有機會我們下次再學習吧~

劇終

更多內容回復查看:

游客,如果您要查看本帖隱藏內容請回復

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的java 线程由浅入深_Java多线程:由浅入深看synchronized的底层实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。

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