多線程中的synchronized鎖機(jī)制

1、synchronized關(guān)鍵字的機(jī)制是對象鎖(把這個對象鎖住【這個對象的帶synchronized關(guān)鍵字的方法鎖住】)

如? ?class A

{

? ? public?synchronized void a()

? ? {

????}

}

在方法a()上加上synchronized關(guān)鍵字,在多個線程中無法同時調(diào)用A類的某個對象的a()方法。

關(guān)鍵字synchronized取得的鎖都是對象鎖,而不是把一段代碼或方法(函數(shù))當(dāng)作鎖,哪個線程先執(zhí)行帶synchronized關(guān)鍵字的方法,哪個線程就持有該方法所屬對象的鎖,其他線程都只能呈等待狀態(tài)。但是這有個前提:既然鎖叫做對象鎖,那么勢必和對象相關(guān),所以多個線程訪問的必須是同一個對象。

如果多個線程訪問的是多個對象,那么Java虛擬機(jī)就會創(chuàng)建多個鎖,既然兩個線程持有的是不同的鎖,自然不會受到"等待釋放鎖"這一行為的制約,可以分別運(yùn)行方法中的代碼。

在一個類中的兩個方法一個加了synchronized,一個未加synchronized,兩個線程是可以同時分別執(zhí)行兩個方法的,但是兩個方法都加synchronized,則必須順序執(zhí)行

兩個結(jié)論:

1、A線程持有Object對象的Lock鎖,B線程可以以異步方式調(diào)用Object對象中的非synchronized類型的方法

2、A線程持有Object對象的Lock鎖,B線程如果在這時調(diào)用Object對象中的synchronized類型的方法則需要等待,也就是同步

換言之,一個線程調(diào)用一個帶了synchronized關(guān)鍵字的方法,則這個線程就獲得了該對象的鎖,其他線程想執(zhí)行該對象的的所有帶synchronized的方法,都得等這個線程執(zhí)行完才可以去競爭。但是可以直接執(zhí)行非同步的方法。

2、synchronized鎖重入

關(guān)鍵字synchronized擁有鎖重入的功能。所謂鎖重入的意思就是:當(dāng)一個線程得到一個對象鎖后,再次請求此對象鎖時時可以再次得到該對象的鎖的。

在一個有synchronized關(guān)鍵的方法中調(diào)用另一個有synchronized關(guān)鍵的方法,該線程將重新獲取該對象的鎖

3、異常自動釋放鎖

當(dāng)一個線程執(zhí)行的代碼出現(xiàn)異常時,其所持有的鎖會自動釋放

4、synchronized同步代碼塊

當(dāng)執(zhí)行一個同步方法時間較長的時候,其他等待線程將會長時間等待,這個情況可以將方法中需要同步的部分設(shè)置為synchronized同步代碼塊,這部分代碼就只有一個縣城能同時執(zhí)行,而其余代碼可以多個線程同時執(zhí)行。

synchronized(this)

? ? ? ? {

。。。。。。。。。。。。。。

? ? ? ? }

結(jié)論:

1、當(dāng)A線程訪問對象的synchronized代碼塊的時候,B線程依然可以訪問對象方法中其余非synchronized塊的部分

2、當(dāng)A線程進(jìn)入對象的synchronized代碼塊的時候,B線程如果要訪問這段synchronized塊,那么訪問將會被阻塞

5、兩個synchronized塊之間具有互斥性

這個與1比較相似,同一個對象的兩個方法中都有synchronized塊,則兩個線程不能同時分別執(zhí)行這兩個帶有synchronized塊的方法,必須順序執(zhí)行。

結(jié)論:synchronized塊獲得的是一個對象鎖,換句話說,synchronized塊鎖定的是整個對象。

6、synchronized塊和synchronized方法

這兩個也是互斥的,執(zhí)行一個,另一個不能執(zhí)行,必須順序執(zhí)行,總之帶synchronized關(guān)鍵字就是鎖住對象。

總結(jié)一下前面的內(nèi)容:

1、synchronized同步方法

(1)對其他synchronized同步方法或synchronized(this)同步代碼塊呈阻塞狀態(tài)

(2)同一時間只有一個線程可以執(zhí)行synchronized同步方法中的代碼

2、synchronized同步代碼塊

(1)對其他synchronized同步方法或synchronized(this)同步代碼塊呈阻塞狀態(tài)

(2)同一時間只有一個線程可以執(zhí)行synchronized(this)同步代碼塊中的代碼

7、將任意對象作為對象監(jiān)視器

Java還支持對"任意對象"作為對象監(jiān)視器來實現(xiàn)同步的功能。這個"任意對象"大多數(shù)是實例變量及方法的參數(shù),使用格式為synchronized(非this對象)

多個線程持有"對象監(jiān)視器"為同一個對象的前提下,同一時間只能有一個線程可以執(zhí)行synchronized(非this對象x)代碼塊中的代碼。(在一個類中,每個synchronized(非this對象x)中的x指示的是同一個變量或參數(shù)的時候,它的作用與synchronized(this)相同)

(1)當(dāng)一個對象的兩個方法的synchronized(x)中的x不同時,他們是不互斥的,兩個線程可以同時調(diào)用這兩個方法(synchronized(this)與同步方法效果一致,一個同步方法和一個x不為this的方法塊也可以同時執(zhí)行)。

(2)當(dāng)多個線程同時執(zhí)行synchronized(x){}同步代碼塊時呈同步效果(只有一個線程能執(zhí)行)

(3)當(dāng)其他線程執(zhí)行x對象中的synchronized同步方法時呈同步效果(比如:有一個同步代碼塊synchronized(A),而A對象中存在是同步方法(同步代碼塊,必須是synchronized(this),必須是this,這樣才能表示這個對象被鎖定),并且有其他線程正在執(zhí)行此方法,也就是A對象被鎖定,這時synchronized(A)這個代碼塊也無法執(zhí)行

(4)當(dāng)其他線程執(zhí)行x對象方法中的synchronized(this)代碼塊時也呈同步效果

其他線程對一個對象的被鎖(X)鎖住(其他線程正在執(zhí)行這段代碼,這個對象的這段代碼就被鎖住了)的代碼是無法執(zhí)行的。

8、同步靜態(tài)方法

擁有 static 與?synchronized兩個關(guān)鍵字的方法

1、如果線程A調(diào)用了某個類的靜態(tài)同步方法(直接通過類名調(diào)用或通過對象調(diào)用),則該類被上鎖(類鎖,和對象鎖不同),則該類中的靜態(tài)同步方法都無法被調(diào)用(直接通過類名調(diào)用或通過對象都無法調(diào)用),但是非靜態(tài)同步方法可以被調(diào)用。

例子:假如一個類中有一個靜態(tài)同步方法A,new出了兩個類的實例B和實例C,線程D持有實例B,線程E持有實例C,只要線程D調(diào)用了A方法,那么線程E調(diào)用A方法必須等待線程D執(zhí)行完A方法,盡管兩個線程持有的是不同的對象。

9、volatile關(guān)鍵字

java有一塊主內(nèi)存,不同線程有不同的工作內(nèi)存,所有變量在主內(nèi)存中有一份,當(dāng)線程需要用到時就去主內(nèi)存中取,用完后,把新值返還給主內(nèi)存。

在啟動一個線程A后,這個A線程將取走它需要的變量a,如果這個變量a被其他的線程B的更改,線程A是無法感知的,也就是線程A每次使用這個變量a時不會再從主內(nèi)存中獲取,就無法保證它取到的是最新的值。

解決辦法:將這個變量前加上volatile關(guān)鍵字。

10、原子類也無法保證線程安全

線程安全不是絕對的,在有邏輯的情況下輸出結(jié)果也具有隨機(jī)性

結(jié)果安全,順序會混亂。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、Synchronized關(guān)鍵字 1、方法中的變量不存在非線程安全問題,都是線程安全的。 2、兩個線程訪問同一個...
    AI喬治閱讀 1,563評論 1 7
  • 本文主要講了java中多線程的使用方法、線程同步、線程數(shù)據(jù)傳遞、線程狀態(tài)及相應(yīng)的一些線程函數(shù)用法、概述等。 首先講...
    李欣陽閱讀 2,597評論 1 15
  • Java多線程學(xué)習(xí) [-] 一擴(kuò)展javalangThread類 二實現(xiàn)javalangRunnable接口 三T...
    影馳閱讀 3,108評論 1 18
  • 林炳文Evankaka原創(chuàng)作品。轉(zhuǎn)載自http://blog.csdn.net/evankaka 本文主要講了ja...
    ccq_inori閱讀 735評論 0 4
  • 寫在前面的話: 這篇博客是我從這里“轉(zhuǎn)載”的,為什么轉(zhuǎn)載兩個字加“”呢?因為這絕不是簡單的復(fù)制粘貼,我花了五六個小...
    SmartSean閱讀 4,946評論 12 45

友情鏈接更多精彩內(nèi)容