摘要:當(dāng)前線程使用將對(duì)象頭的替換為鎖記錄指針,如果成功,當(dāng)前線程獲得鎖如果失敗,表示其他線程競爭鎖,當(dāng)前線程便嘗試使用自旋來獲取鎖。重量級(jí)鎖是悲觀鎖的一種,自旋鎖輕量級(jí)鎖與偏向鎖屬于樂觀鎖。
操作系統(tǒng)在面對(duì)線程間同步的時(shí)候,會(huì)支持例如semaphore信號(hào)量和mutex互斥量等同步原語,而monitor是在編程語言中被實(shí)現(xiàn)的,下面介紹一下java中monitor(監(jiān)視器/管程:管理共享變量以及對(duì)其的操作過程,讓他們支持并發(fā))的實(shí)現(xiàn)原理:
以一個(gè)阻塞隊(duì)列的實(shí)現(xiàn)來舉例:
同時(shí),java內(nèi)置的synchronized關(guān)鍵字可以認(rèn)為是MESA模型的簡化版,其只能有一個(gè)條件變量,但編譯器會(huì)自動(dòng)添加加鎖與解鎖的代碼。synchronized關(guān)鍵字可以修飾實(shí)例方法、類方法以及代碼塊,如果修飾的是代碼塊,需要制定關(guān)聯(lián)的Object;如果修飾的是實(shí)例方法,那么其關(guān)聯(lián)的對(duì)象實(shí)際上是this;如果修飾的是類方法,那么其關(guān)聯(lián)的對(duì)象是this.class。這些關(guān)聯(lián)的對(duì)象就是MESA模型里的條件變量。
synchronized實(shí)現(xiàn)原理JVM基于進(jìn)入和退出monitor對(duì)象來實(shí)現(xiàn)同步,同步代碼塊采用添加moniterenter、moniterexit,同步方法使用ACC_SYNCHRONIZED標(biāo)記符隱式實(shí)現(xiàn)。每個(gè)對(duì)象都有一個(gè)monitor與之關(guān)聯(lián),運(yùn)行到moniterenter時(shí)嘗試獲取對(duì)應(yīng)monitor的所有權(quán),獲取成功就將monitor的進(jìn)入數(shù)加1(所以是可重入鎖,也被稱為重量級(jí)鎖),否則就阻塞,擁有monitor的線程運(yùn)行到moniterexit時(shí)進(jìn)入數(shù)減1,為0時(shí)釋放monitor。
java中每個(gè)對(duì)象都有一個(gè)對(duì)象頭,synchronized所用的鎖就是存在對(duì)象頭里的。如果是非數(shù)組的對(duì)象是8個(gè)字節(jié)(32位JVM)或者16字節(jié)(64位JVM),數(shù)組對(duì)象還會(huì)有一個(gè)數(shù)組長度(4個(gè)字節(jié))。以32位JVM非數(shù)組對(duì)象為例:
鎖信息就存在前4個(gè)字節(jié)的MarkWord中,JVM對(duì)synchronized的加鎖過程優(yōu)化為:
檢測(cè)Mark Word里面是不是當(dāng)前線程的ID,如果是,表示當(dāng)前線程處于偏向鎖
如果不是,則使用CAS將當(dāng)前線程的ID替換Mard Word,如果成功則表示當(dāng)前線程獲得偏向鎖,置偏向標(biāo)志位1
如果失敗,則說明發(fā)生競爭,撤銷偏向鎖,進(jìn)而升級(jí)為輕量級(jí)鎖。
當(dāng)前線程使用CAS將對(duì)象頭的Mark Word替換為鎖記錄指針,如果成功,當(dāng)前線程獲得鎖
如果失敗,表示其他線程競爭鎖,當(dāng)前線程便嘗試使用自旋來獲取鎖。
如果自旋成功則依然處于輕量級(jí)狀態(tài)。
如果自旋失敗,則升級(jí)為重量級(jí)鎖。
重量級(jí)鎖是悲觀鎖的一種,自旋鎖、輕量級(jí)鎖與偏向鎖屬于樂觀鎖。
CAS設(shè)計(jì)讀取-比較-寫入三個(gè)操作,是在CPU指令層面保證其原子性,volatile是保證多線程下的內(nèi)存可見性,二者需配合使用。另外還需注意CPU緩存行(一次以32/64字節(jié)為單位從主內(nèi)存中讀取數(shù)據(jù)到緩存)包含多個(gè)變量所帶來的隱形同步問題:其中一個(gè)變量被volatile修飾,導(dǎo)致另外一個(gè)變量在另一個(gè)CPU核上(另一個(gè)線程)的讀寫也要被強(qiáng)制刷新緩存。
管程:并發(fā)編程的萬能鑰匙
java 中的鎖 -- 偏向鎖、輕量級(jí)鎖、自旋鎖、重量級(jí)鎖
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/77770.html
摘要:語言在之前,提供的唯一的并發(fā)原語就是管程,而且之后提供的并發(fā)包,也是以管程技術(shù)為基礎(chǔ)的。但是管程更容易使用,所以選擇了管程。線程進(jìn)入條件變量的等待隊(duì)列后,是允許其他線程進(jìn)入管程的。并發(fā)編程里兩大核心問題互斥和同步,都可以由管程來幫你解決。 并發(fā)編程這個(gè)技術(shù)領(lǐng)域已經(jīng)發(fā)展了半個(gè)世紀(jì)了。有沒有一種核心技術(shù)可以很方便地解決我們的并發(fā)問題呢?這個(gè)問題, 我會(huì)選擇 Monitor(管程)技術(shù)。Ja...
摘要:請(qǐng)參看前一篇文章并發(fā)學(xué)習(xí)筆記一原子性可見性有序性問題六等待通知機(jī)制什么是等待通知機(jī)制當(dāng)線程不滿足某個(gè)條件,則進(jìn)入等待狀態(tài)如果線程滿足要求的某個(gè)條件后,則通知等待的線程重新執(zhí)行。經(jīng)極客時(shí)間并發(fā)編程實(shí)戰(zhàn)專欄內(nèi)容學(xué)習(xí)整理 請(qǐng)參看前一篇文章:Java 并發(fā)學(xué)習(xí)筆記(一)——原子性、可見性、有序性問題 六、等待—通知機(jī)制 什么是等待通知—機(jī)制?當(dāng)線程不滿足某個(gè)條件,則進(jìn)入等待狀態(tài);如果線程滿足要...
摘要:基本元素機(jī)制需要幾個(gè)元素來配合,分別是臨界區(qū)對(duì)象及鎖條件變量以及定義在對(duì)象上的,操作。這個(gè)外部條件在機(jī)制中稱為條件變量。提供的機(jī)制,其實(shí)是,等元素合作形成的,甚至說外部的條件變量也是個(gè)組成部分。 monitor的概念 管程,英文是 Monitor,也常被翻譯為監(jiān)視器,monitor 不管是翻譯為管程還是監(jiān)視器,都是比較晦澀的,通過翻譯后的中文,并無法對(duì) monitor 達(dá)到一個(gè)直觀的描...
摘要:那并發(fā)里面的理論和模型是什么呢那便要從操作系統(tǒng)中解決并發(fā)問題的一種模型管程講起了。當(dāng)一個(gè)進(jìn)程使用完管程后,它必須釋放管程并喚醒等待管程的某一個(gè)進(jìn)程。總結(jié)在并發(fā)編程領(lǐng)域,有兩大核心問題互斥和同步,而這兩個(gè)問題,管程模型都可以解決。 為什么需要了解管程 Java并發(fā)編程是Java中高級(jí)程序員必備的一項(xiàng)技能,但是真正學(xué)明白并發(fā)編程也并非易事。正如Java并發(fā)編程實(shí)踐中的一句話編寫正確的程序并...
摘要:由此可見,自旋鎖和各有優(yōu)劣,他們分別適用于競爭不多和競爭激烈的場景中。每一個(gè)試圖進(jìn)入同步代碼塊的線程都會(huì)被封裝成對(duì)象,它們或在對(duì)象的中,或在中,等待成為對(duì)象的成為的對(duì)象即獲取了監(jiān)視器鎖。 前言 系列文章目錄 前面兩篇文章我們介紹了synchronized同步代碼塊以及wait和notify機(jī)制,大致知道了這些關(guān)鍵字和方法是干什么的,以及怎么用。 但是,知其然,并不知其所以然。 例如...
閱讀 3669·2021-11-23 09:51
閱讀 1660·2021-10-22 09:53
閱讀 1345·2021-10-09 09:56
閱讀 853·2019-08-30 13:47
閱讀 2155·2019-08-30 12:55
閱讀 1596·2019-08-30 12:46
閱讀 1104·2019-08-30 10:51
閱讀 2409·2019-08-29 12:43