Java中synchronized同步块的执行流程
必要知識(shí)
Java 對(duì)象的數(shù)據(jù)結(jié)構(gòu)
- 在 HotSpot 虛擬機(jī)中,Java 對(duì)象在內(nèi)存中存儲(chǔ)的布局可以分為 3 塊區(qū)域:對(duì)象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)和對(duì)齊填充(Padding)
- 對(duì)象頭中的 Mark Word 部分,用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)、GC 分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程 ID、偏向時(shí)間戳等,其中的最后 2bit 是鎖狀態(tài)標(biāo)志位(無(wú)鎖、偏向鎖、輕量級(jí)鎖、重量級(jí)鎖、GC 標(biāo)識(shí))
鎖升級(jí)流程
無(wú)鎖 -> 偏向鎖 -> 輕量級(jí)鎖 -> 重量級(jí)鎖
無(wú)鎖: 沒(méi)有對(duì)資源進(jìn)行鎖定,所有的線程都能訪問(wèn)并修改同一個(gè)資源,但同時(shí)只有一個(gè)線程能修改成功,其他修改失敗的線程會(huì)不斷重試直到修改成功。
偏向鎖:對(duì)象的代碼一直被同一線程執(zhí)行,不存在多個(gè)線程競(jìng)爭(zhēng),該線程在后續(xù)的執(zhí)行中自動(dòng)獲取鎖,降低獲取鎖帶來(lái)的性能開(kāi)銷。偏向鎖,指的就是偏向第一個(gè)加鎖線程,該線程是不會(huì)主動(dòng)釋放偏向鎖的,只有當(dāng)其他線程嘗試競(jìng)爭(zhēng)偏向鎖才會(huì)被釋放。
偏向鎖的撤銷,需要在某個(gè)時(shí)間點(diǎn)上沒(méi)有字節(jié)碼正在執(zhí)行時(shí),先暫停擁有偏向鎖的線程,然后判斷鎖對(duì)象是否處于被鎖定狀態(tài)。如果線程不處于活動(dòng)狀態(tài),則將對(duì)象頭設(shè)置成無(wú)鎖狀態(tài),并撤銷偏向鎖;
如果線程處于活動(dòng)狀態(tài),升級(jí)為輕量級(jí)鎖的狀態(tài)。
輕量級(jí)鎖(樂(lè)觀鎖):輕量級(jí)鎖是指當(dāng)鎖是偏向鎖的時(shí)候,被第二個(gè)線程 B 所訪問(wèn),此時(shí)偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖,線程 B 會(huì)通過(guò)自旋的形式嘗試獲取鎖,線程不會(huì)阻塞,從而提高性能。
當(dāng)前只有一個(gè)等待線程,則該線程將通過(guò)自旋進(jìn)行等待。但是當(dāng)自旋超過(guò)一定的次數(shù)時(shí),輕量級(jí)鎖便會(huì)升級(jí)為重量級(jí)鎖;當(dāng)一個(gè)線程已持有鎖,另一個(gè)線程在自旋,而此時(shí)又有第三個(gè)線程來(lái)訪時(shí),輕量級(jí)鎖也會(huì)升級(jí)為重量級(jí)鎖。
重量級(jí)鎖(悲觀鎖):指當(dāng)有一個(gè)線程獲取鎖之后,其余所有等待獲取該鎖的線程都會(huì)處于阻塞狀態(tài)。
重量級(jí)鎖通過(guò)對(duì)象內(nèi)部的監(jiān)視器(monitor)實(shí)現(xiàn),而其中 monitor 的本質(zhì)是依賴于底層操作系統(tǒng)的 Mutex Lock 實(shí)現(xiàn),操作系統(tǒng)實(shí)現(xiàn)線程之間的切換需要從用戶態(tài)切換到內(nèi)核態(tài),切換成本非常高。
synchronized 的執(zhí)行過(guò)程
在所有的鎖都啟用的情況下,線程進(jìn)入臨界區(qū)時(shí)會(huì)先去獲取偏向鎖,如果已經(jīng)存在偏向鎖了,則會(huì)嘗試獲取輕量級(jí)鎖,啟用自旋鎖,如果自旋也沒(méi)有獲取到鎖,則使用重量級(jí)鎖,沒(méi)有獲取到鎖的線程阻塞掛起,直到持有鎖的線程執(zhí)行完同步塊喚醒他們
總結(jié)
以上是生活随笔為你收集整理的Java中synchronized同步块的执行流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 画蛇添足的寓意是什么 画蛇添足的故事告诉
- 下一篇: important的反义词 import