国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - 鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

2021-03-31 23:15牧小農(nóng) Java教程

文中講述了java中鎖的四種狀態(tài)以及鎖是如何一步一步升級(jí)的過(guò)程,有需要的朋友可以參考下。

鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

一、前言

 

的狀態(tài)總共有四種,級(jí)別由低到高依次為:無(wú)鎖、偏向鎖、輕量級(jí)鎖、重量級(jí)鎖,這四種鎖狀態(tài)分別代表什么,為什么會(huì)有鎖升級(jí)?其實(shí)在 JDK 1.6之前,synchronized 還是一個(gè)重量級(jí)鎖,是一個(gè)效率比較低下的鎖,但是在JDK 1.6后,Jvm為了提高鎖的獲取與釋放效率對(duì)(synchronized )進(jìn)行了優(yōu)化,引入了 偏向鎖 和 輕量級(jí)鎖 ,從此以后鎖的狀態(tài)就有了四種(無(wú)鎖、偏向鎖、輕量級(jí)鎖、重量級(jí)鎖),并且四種狀態(tài)會(huì)隨著競(jìng)爭(zhēng)的情況逐漸升級(jí),而且是不可逆的過(guò)程,即不可降級(jí),也就是說(shuō)只能進(jìn)行鎖升級(jí)(從低級(jí)別到高級(jí)別),不能鎖降級(jí)(高級(jí)別到低級(jí)別),意味著偏向鎖升級(jí)成輕量級(jí)鎖后不能降級(jí)成偏向鎖。這種鎖升級(jí)卻不能降級(jí)的策略,目的是為了提高獲得鎖和釋放鎖的效率。

二、鎖的四種狀態(tài)

 

在 synchronized 最初的實(shí)現(xiàn)方式是 “阻塞或喚醒一個(gè)Java線程需要操作系統(tǒng)切換CPU狀態(tài)來(lái)完成,這種狀態(tài)切換需要耗費(fèi)處理器時(shí)間,如果同步代碼塊中內(nèi)容過(guò)于簡(jiǎn)單,這種切換的時(shí)間可能比用戶代碼執(zhí)行的時(shí)間還長(zhǎng)”,這種方式就是 synchronized實(shí)現(xiàn)同步最初的方式,這也是當(dāng)初開(kāi)發(fā)者詬病的地方,這也是在JDK6以前 synchronized效率低下的原因,JDK6中為了減少獲得鎖和釋放鎖帶來(lái)的性能消耗,引入了“偏向鎖”和“輕量級(jí)鎖”。

所以目前鎖狀態(tài)一種有四種,從級(jí)別由低到高依次是:無(wú)鎖、偏向鎖,輕量級(jí)鎖,重量級(jí)鎖,鎖狀態(tài)只能升級(jí),不能降級(jí)

如圖所示:

鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

三、鎖狀態(tài)的思路以及特點(diǎn)

 

鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

四、鎖對(duì)比

 

鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

五、Synchronized鎖

 

synchronized 用的鎖是存在Java對(duì)象頭里的,那么什么是對(duì)象頭呢?

5.1 Java 對(duì)象頭

我們以 Hotspot 虛擬機(jī)為例,Hopspot 對(duì)象頭主要包括兩部分?jǐn)?shù)據(jù):MarkWord(標(biāo)記字段)和KlassPointer(類(lèi)型指針)

Mark Word:默認(rèn)存儲(chǔ)對(duì)象的HashCode,分代年齡和鎖標(biāo)志位信息。這些信息都是與對(duì)象自身定義無(wú)關(guān)的數(shù)據(jù),所以Mark Word被設(shè)計(jì)成一個(gè)非固定的數(shù)據(jù)結(jié)構(gòu)以便在極小的空間內(nèi)存存儲(chǔ)盡量多的數(shù)據(jù)。它會(huì)根據(jù)對(duì)象的狀態(tài)復(fù)用自己的存儲(chǔ)空間,也就是說(shuō)在運(yùn)行期間Mark Word里存儲(chǔ)的數(shù)據(jù)會(huì)隨著鎖標(biāo)志位的變化而變化。

Klass Point:對(duì)象指向它的類(lèi)元數(shù)據(jù)的指針,虛擬機(jī)通過(guò)這個(gè)指針來(lái)確定這個(gè)對(duì)象是哪個(gè)類(lèi)的實(shí)例。

在上面中我們知道了, synchronized 用的鎖是存在Java對(duì)象頭里的,那么具體是存在對(duì)象頭哪里呢?答案是:存在鎖對(duì)象的對(duì)象頭的Mark Word中,那么MarkWord在對(duì)象頭中到底長(zhǎng)什么樣,它到底存儲(chǔ)了什么呢?

在64位的虛擬機(jī)中:

鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

在32位的虛擬機(jī)中:

 鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

下面我們以 32位虛擬機(jī)為例,來(lái)看一下其 Mark Word 的字節(jié)具體是如何分配的

無(wú)鎖:對(duì)象頭開(kāi)辟 25bit 的空間用來(lái)存儲(chǔ)對(duì)象的 hashcode ,4bit 用于存放對(duì)象分代年齡,1bit 用來(lái)存放是否偏向鎖的標(biāo)識(shí)位,2bit 用來(lái)存放鎖標(biāo)識(shí)位為01

偏向鎖: 在偏向鎖中劃分更細(xì),還是開(kāi)辟 25bit 的空間,其中23bit 用來(lái)存放線程ID,2bit 用來(lái)存放 Epoch,4bit 存放對(duì)象分代年齡,1bit 存放是否偏向鎖標(biāo)識(shí), 0表示無(wú)鎖,1表示偏向鎖,鎖的標(biāo)識(shí)位還是01

輕量級(jí)鎖:在輕量級(jí)鎖中直接開(kāi)辟 30bit 的空間存放指向棧中鎖記錄的指針,2bit 存放鎖的標(biāo)志位,其標(biāo)志位為00

重量級(jí)鎖: 在重量級(jí)鎖中和輕量級(jí)鎖一樣,30bit 的空間用來(lái)存放指向重量級(jí)鎖的指針,2bit 存放鎖的標(biāo)識(shí)位,為11

GC標(biāo)記: 開(kāi)辟30bit 的內(nèi)存空間卻沒(méi)有占用,2bit 空間存放鎖標(biāo)志位為11。

其中無(wú)鎖和偏向鎖的鎖標(biāo)志位都是01,只是在前面的1bit區(qū)分了這是無(wú)鎖狀態(tài)還是偏向鎖狀態(tài)

關(guān)于內(nèi)存的分配,我們可以在git中openJDK中 markOop.hpp 可以看出:

  1. public
  2.   // Constants 
  3.   enum { age_bits                 = 4, 
  4.          lock_bits                = 2, 
  5.          biased_lock_bits         = 1, 
  6.          max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits, 
  7.          hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits, 
  8.          cms_bits                 = LP64_ONLY(1) NOT_LP64(0), 
  9.          epoch_bits               = 2 
  10.   }; 
  • age_bits: 就是我們說(shuō)的分代回收的標(biāo)識(shí),占用4字節(jié)
  • lock_bits: 是鎖的標(biāo)志位,占用2個(gè)字節(jié)
  • biasedlockbits: 是是否偏向鎖的標(biāo)識(shí),占用1個(gè)字節(jié)
  • maxhashbits: 是針對(duì)無(wú)鎖計(jì)算的hashcode 占用字節(jié)數(shù)量,如果是32位虛擬機(jī),就是 32 - 4 - 2 -1 = 25 byte,如果是64 位虛擬機(jī),64 - 4 - 2 - 1 = 57 byte,但是會(huì)有 25 字節(jié)未使用,所以64位的 hashcode 占用 31 byte
  • hash_bits: 是針對(duì) 64 位虛擬機(jī)來(lái)說(shuō),如果最大字節(jié)數(shù)大于 31,則取31,否則取真實(shí)的字節(jié)數(shù)
  • cms_bits: 不是64位虛擬機(jī)就占用 0 byte,是64位就占用 1byte
  • epoch_bits: 就是 epoch 所占用的字節(jié)大小,2字節(jié)。

5.2 Monitor

Monitor 可以理解為一個(gè)同步工具或一種同步機(jī)制,通常被描述為一個(gè)對(duì)象。每一個(gè) Java 對(duì)象就有一把看不見(jiàn)的鎖,稱(chēng)為內(nèi)部鎖或者 Monitor 鎖。

Monitor 是線程私有的數(shù)據(jù)結(jié)構(gòu),每一個(gè)線程都有一個(gè)可用 monitor record 列表,同時(shí)還有一個(gè)全局的可用列表。每一個(gè)被鎖住的對(duì)象都會(huì)和一個(gè) monitor 關(guān)聯(lián),同時(shí) monitor 中有一個(gè) Owner 字段存放擁有該鎖的線程的唯一標(biāo)識(shí),表示該鎖被這個(gè)線程占用。

Synchronized是通過(guò)對(duì)象內(nèi)部的一個(gè)叫做監(jiān)視器鎖(monitor)來(lái)實(shí)現(xiàn)的,監(jiān)視器鎖本質(zhì)又是依賴于底層的操作系統(tǒng)的 Mutex Lock(互斥鎖)來(lái)實(shí)現(xiàn)的。而操作系統(tǒng)實(shí)現(xiàn)線程之間的切換需要從用戶態(tài)轉(zhuǎn)換到核心態(tài),這個(gè)成本非常高,狀態(tài)之間的轉(zhuǎn)換需要相對(duì)比較長(zhǎng)的時(shí)間,這就是為什么 Synchronized 效率低的原因。因此,這種依賴于操作系統(tǒng) Mutex Lock 所實(shí)現(xiàn)的鎖我們稱(chēng)之為重量級(jí)鎖。

隨著鎖的競(jìng)爭(zhēng),鎖可以從偏向鎖升級(jí)到輕量級(jí)鎖,再升級(jí)的重量級(jí)鎖(但是鎖的升級(jí)是單向的,也就是說(shuō)只能從低到高升級(jí),不會(huì)出現(xiàn)鎖的降級(jí))。JDK 1.6中默認(rèn)是開(kāi)啟偏向鎖和輕量級(jí)鎖的,我們也可以通過(guò)-XX:-UseBiasedLocking=false來(lái)禁用偏向鎖。

六、鎖的分類(lèi)

 

6.2 無(wú)鎖

無(wú)鎖是指沒(méi)有對(duì)資源進(jìn)行鎖定,所有的線程都能訪問(wèn)并修改同一個(gè)資源,但同時(shí)只有一個(gè)線程能修改成功。

無(wú)鎖的特點(diǎn)是修改操作會(huì)在循環(huán)內(nèi)進(jìn)行,線程會(huì)不斷的嘗試修改共享資源。如果沒(méi)有沖突就修改成功并退出,否則就會(huì)繼續(xù)循環(huán)嘗試。如果有多個(gè)線程修改同一個(gè)值,必定會(huì)有一個(gè)線程能修改成功,而其他修改失敗的線程會(huì)不斷重試直到修改成功。

6.3 偏向鎖

初次執(zhí)行到synchronized代碼塊的時(shí)候,鎖對(duì)象變成偏向鎖(通過(guò)CAS修改對(duì)象頭里的鎖標(biāo)志位),字面意思是“偏向于第一個(gè)獲得它的線程”的鎖。執(zhí)行完同步代碼塊后,線程并不會(huì)主動(dòng)釋放偏向鎖。當(dāng)?shù)诙蔚竭_(dá)同步代碼塊時(shí),線程會(huì)判斷此時(shí)持有鎖的線程是否就是自己(持有鎖的線程ID也在對(duì)象頭里),如果是則正常往下執(zhí)行。由于之前沒(méi)有釋放鎖,這里也就不需要重新加鎖。如果自始至終使用鎖的線程只有一個(gè),很明顯偏向鎖幾乎沒(méi)有額外開(kāi)銷(xiāo),性能極高。

偏向鎖是指當(dāng)一段同步代碼一直被同一個(gè)線程所訪問(wèn)時(shí),即不存在多個(gè)線程的競(jìng)爭(zhēng)時(shí),那么該線程在后續(xù)訪問(wèn)時(shí)便會(huì)自動(dòng)獲得鎖,從而降低獲取鎖帶來(lái)的消耗,即提高性能。

當(dāng)一個(gè)線程訪問(wèn)同步代碼塊并獲取鎖時(shí),會(huì)在 Mark Word 里存儲(chǔ)鎖偏向的線程 ID。在線程進(jìn)入和退出同步塊時(shí)不再通過(guò) CAS 操作來(lái)加鎖和解鎖,而是檢測(cè) Mark Word 里是否存儲(chǔ)著指向當(dāng)前線程的偏向鎖。輕量級(jí)鎖的獲取及釋放依賴多次 CAS 原子指令,而偏向鎖只需要在置換 ThreadID 的時(shí)候依賴一次 CAS 原子指令即可。

偏向鎖只有遇到其他線程嘗試競(jìng)爭(zhēng)偏向鎖時(shí),持有偏向鎖的線程才會(huì)釋放鎖,線程是不會(huì)主動(dòng)釋放偏向鎖的。

關(guān)于偏向鎖的撤銷(xiāo),需要等待全局安全點(diǎn),即在某個(gè)時(shí)間點(diǎn)上沒(méi)有字節(jié)碼正在執(zhí)行時(shí),它會(huì)先暫停擁有偏向鎖的線程,然后判斷鎖對(duì)象是否處于被鎖定狀態(tài)。如果線程不處于活動(dòng)狀態(tài),則將對(duì)象頭設(shè)置成無(wú)鎖狀態(tài),并撤銷(xiāo)偏向鎖,恢復(fù)到無(wú)鎖(標(biāo)志位為01)或輕量級(jí)鎖(標(biāo)志位為00)的狀態(tài)。

6.4 輕量級(jí)鎖(自旋鎖)

 鎖的四種狀態(tài)與鎖升級(jí)過(guò)程

輕量級(jí)鎖是指當(dāng)鎖是偏向鎖的時(shí)候,卻被另外的線程所訪問(wèn),此時(shí)偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖,其他線程會(huì)通過(guò)自旋(關(guān)于自旋的介紹見(jiàn)文末)的形式嘗試獲取鎖,線程不會(huì)阻塞,從而提高性能。

輕量級(jí)鎖的獲取主要由兩種情況:① 當(dāng)關(guān)閉偏向鎖功能時(shí);② 由于多個(gè)線程競(jìng)爭(zhēng)偏向鎖導(dǎo)致偏向鎖升級(jí)為輕量級(jí)鎖。

一旦有第二個(gè)線程加入鎖競(jìng)爭(zhēng),偏向鎖就升級(jí)為輕量級(jí)鎖(自旋鎖)。這里要明確一下什么是鎖競(jìng)爭(zhēng):如果多個(gè)線程輪流獲取一個(gè)鎖,但是每次獲取鎖的時(shí)候都很順利,沒(méi)有發(fā)生阻塞,那么就不存在鎖競(jìng)爭(zhēng)。只有當(dāng)某線程嘗試獲取鎖的時(shí)候,發(fā)現(xiàn)該鎖已經(jīng)被占用,只能等待其釋放,這才發(fā)生了鎖競(jìng)爭(zhēng)。

在輕量級(jí)鎖狀態(tài)下繼續(xù)鎖競(jìng)爭(zhēng),沒(méi)有搶到鎖的線程將自旋,即不停地循環(huán)判斷鎖是否能夠被成功獲取。獲取鎖的操作,其實(shí)就是通過(guò)CAS修改對(duì)象頭里的鎖標(biāo)志位。先比較當(dāng)前鎖標(biāo)志位是否為“釋放”,如果是則將其設(shè)置為“鎖定”,比較并設(shè)置是原子性發(fā)生的。這就算搶到鎖了,然后線程將當(dāng)前鎖的持有者信息修改為自己。

長(zhǎng)時(shí)間的自旋操作是非常消耗資源的,一個(gè)線程持有鎖,其他線程就只能在原地空耗CPU,執(zhí)行不了任何有效的任務(wù),這種現(xiàn)象叫做忙等(busy-waiting)。如果多個(gè)線程用一個(gè)鎖,但是沒(méi)有發(fā)生鎖競(jìng)爭(zhēng),或者發(fā)生了很輕微的鎖競(jìng)爭(zhēng),那么synchronized就用輕量級(jí)鎖,允許短時(shí)間的忙等現(xiàn)象。這是一種折衷的想法,短時(shí)間的忙等,換取線程在用戶態(tài)和內(nèi)核態(tài)之間切換的開(kāi)銷(xiāo)。

6.4 重量級(jí)鎖

重量級(jí)鎖顯然,此忙等是有限度的(有個(gè)計(jì)數(shù)器記錄自旋次數(shù),默認(rèn)允許循環(huán)10次,可以通過(guò)虛擬機(jī)參數(shù)更改)。如果鎖競(jìng)爭(zhēng)情況嚴(yán)重,某個(gè)達(dá)到最大自旋次數(shù)的線程,會(huì)將輕量級(jí)鎖升級(jí)為重量級(jí)鎖(依然是CAS修改鎖標(biāo)志位,但不修改持有鎖的線程ID)。當(dāng)后續(xù)線程嘗試獲取鎖時(shí),發(fā)現(xiàn)被占用的鎖是重量級(jí)鎖,則直接將自己掛起(而不是忙等),等待將來(lái)被喚醒。

重量級(jí)鎖是指當(dāng)有一個(gè)線程獲取鎖之后,其余所有等待獲取該鎖的線程都會(huì)處于阻塞狀態(tài)。

簡(jiǎn)言之,就是所有的控制權(quán)都交給了操作系統(tǒng),由操作系統(tǒng)來(lái)負(fù)責(zé)線程間的調(diào)度和線程的狀態(tài)變更。而這樣會(huì)出現(xiàn)頻繁地對(duì)線程運(yùn)行狀態(tài)的切換,線程的掛起和喚醒,從而消耗大量的系統(tǒng)資

五、總結(jié)

文中講述了鎖的四種狀態(tài)以及鎖是如何一步一步升級(jí)的過(guò)程,

原文地址:https://mp.weixin.qq.com/s/Lnx1j4njDymcxkAK2ZbwAg

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: www中文字幕 | 青青操原 | 亚洲美腿 欧美 激情 另类 | 日韩亚洲视频 | 亚洲男人在线天堂 | 99久久精品一区二区成人 | 欧美久久免费 | 伊人色爱| 黄色片小视频 | av网站在线免费观看 | 国产片av在线永久免费观看 | 亚洲国产精品久久久 | 国产一区二区三区在线免费观看 | 999精品| 视频国产一区 | 中文字幕一区在线 | 中文字幕亚洲欧美 | 亚洲综合一区二区三区 | 精品国产一区二区三区免费 | 一本久久a久久精品亚洲 | 欧美成人激情视频 | 欧美第5页| 激情久久婷婷 | 欧美日韩国产一区二区在线观看 | 日韩有码在线播放 | 亚洲a网站 | 欧美日韩在线一区二区三区 | 久久久久久国产精品mv | 日韩国产一区二区三区 | 精品日韩一区二区 | 欧美一区免费 | 日韩爱爱免费视频 | 中文字幕av网站 | 精品国产精品三级精品av网址 | 免费日韩精品 | jlzzjlzz亚洲日本少妇 | 成人免费av| 国产一区二区三区在线免费 | 免费一二区 | 久久精品视频一区 | 日韩一二三 |