Java并发编程(7):使用synchronized获取互斥锁的几点说明
在并發(fā)編程中,多線程同時(shí)并發(fā)訪問的資源叫做臨界資源,當(dāng)多個(gè)線程同時(shí)訪問對(duì)象并要求操作相同資源時(shí),分割了原子操作就有可能出現(xiàn)數(shù)據(jù)的不一致或數(shù)據(jù)不完整的情況,為避免這種情況的發(fā)生,我們會(huì)采取同步機(jī)制,以確保在某一時(shí)刻,方法內(nèi)只允許有一個(gè)線程。
采用synchronized修飾符實(shí)現(xiàn)的同步機(jī)制叫做互斥鎖機(jī)制,它所獲得的鎖叫做互斥鎖。每個(gè)對(duì)象都有一個(gè)monitor(鎖標(biāo)記),當(dāng)線程擁有這個(gè)鎖標(biāo)記時(shí)才能訪問這個(gè)資源,沒有鎖標(biāo)記便進(jìn)入鎖池。任何一個(gè)對(duì)象系統(tǒng)都會(huì)為其創(chuàng)建一個(gè)互斥鎖,這個(gè)鎖是為了分配給線程的,防止打斷原子操作。每個(gè)對(duì)象的鎖只能分配給一個(gè)線程,因此叫做互斥鎖。
這里就使用同步機(jī)制獲取互斥鎖的情況,進(jìn)行幾點(diǎn)說(shuō)明:
1、如果同一個(gè)方法內(nèi)同時(shí)有兩個(gè)或更多線程,則每個(gè)線程有自己的局部變量拷貝。
2、類的每個(gè)實(shí)例都有自己的對(duì)象級(jí)別鎖。當(dāng)一個(gè)線程訪問實(shí)例對(duì)象中的synchronized同步代碼塊或同步方法時(shí),該線程便獲取了該實(shí)例的對(duì)象級(jí)別鎖,其他線程這時(shí)如果要訪問synchronized同步代碼塊或同步方法,便需要阻塞等待,直到前面的線程從同步代碼塊或方法中退出,釋放掉了該對(duì)象級(jí)別鎖。
3、訪問同一個(gè)類的不同實(shí)例對(duì)象中的同步代碼塊,不存在阻塞等待獲取對(duì)象鎖的問題,因?yàn)樗鼈儷@取的是各自實(shí)例的對(duì)象級(jí)別鎖,相互之間沒有影響。
4、持有一個(gè)對(duì)象級(jí)別鎖不會(huì)阻止該線程被交換出來(lái),也不會(huì)阻塞其他線程訪問同一示例對(duì)象中的非synchronized代碼。當(dāng)一個(gè)線程A持有一個(gè)對(duì)象級(jí)別鎖(即進(jìn)入了synchronized修飾的代碼塊或方法中)時(shí),線程也有可能被交換出去,此時(shí)線程B有可能獲取執(zhí)行該對(duì)象中代碼的時(shí)間,但它只能執(zhí)行非同步代碼(沒有用synchronized修飾),當(dāng)執(zhí)行到同步代碼時(shí),便會(huì)被阻塞,此時(shí)可能線程規(guī)劃器又讓A線程運(yùn)行,A線程繼續(xù)持有對(duì)象級(jí)別鎖,當(dāng)A線程退出同步代碼時(shí)(即釋放了對(duì)象級(jí)別鎖),如果B線程此時(shí)再運(yùn)行,便會(huì)獲得該對(duì)象級(jí)別鎖,從而執(zhí)行synchronized中的代碼。
5、持有對(duì)象級(jí)別鎖的線程會(huì)讓其他線程阻塞在所有的synchronized代碼外。例如,在一個(gè)類中有三個(gè)synchronized方法a,b,c,當(dāng)線程A正在執(zhí)行一個(gè)實(shí)例對(duì)象M中的方法a時(shí),它便獲得了該對(duì)象級(jí)別鎖,那么其他的線程在執(zhí)行同一實(shí)例對(duì)象(即對(duì)象M)中的代碼時(shí),便會(huì)在所有的synchronized方法處阻塞,即在方法a,b,c處都要被阻塞,等線程A釋放掉對(duì)象級(jí)別鎖時(shí),其他的線程才可以去執(zhí)行方法a,b或者c中的代碼,從而獲得該對(duì)象級(jí)別鎖。
6、使用synchronized(obj)同步語(yǔ)句塊,可以獲取指定對(duì)象上的對(duì)象級(jí)別鎖。obj為對(duì)象的引用,如果獲取了obj對(duì)象上的對(duì)象級(jí)別鎖,在并發(fā)訪問obj對(duì)象時(shí)時(shí),便會(huì)在其synchronized代碼處阻塞等待,直到獲取到該obj對(duì)象的對(duì)象級(jí)別鎖。當(dāng)obj為this時(shí),便是獲取當(dāng)前對(duì)象的對(duì)象級(jí)別鎖。
7、類級(jí)別鎖被特定類的所有示例共享,它用于控制對(duì)static成員變量以及static方法的并發(fā)訪問。具體用法與對(duì)象級(jí)別鎖相似。
8、互斥是實(shí)現(xiàn)同步的一種手段,臨界區(qū)、互斥量和信號(hào)量都是主要的互斥實(shí)現(xiàn)方式。synchronized關(guān)鍵字經(jīng)過(guò)編譯后,會(huì)在同步塊的前后分別形成monitorenter和monitorexit這兩個(gè)字節(jié)碼指令。根據(jù)虛擬機(jī)規(guī)范的要求,在執(zhí)行monitorenter指令時(shí),首先要嘗試獲取對(duì)象的鎖,如果獲得了鎖,把鎖的計(jì)數(shù)器加1,相應(yīng)地,在執(zhí)行monitorexit指令時(shí)會(huì)將鎖計(jì)數(shù)器減1,當(dāng)計(jì)數(shù)器為0時(shí),鎖便被釋放了。由于synchronized同步塊對(duì)同一個(gè)線程是可重入的,因此一個(gè)線程可以多次獲得同一個(gè)對(duì)象的互斥鎖,同樣,要釋放相應(yīng)次數(shù)的該互斥鎖,才能最終釋放掉該鎖。
from:?http://www.importnew.com/20607.html
原文出處:?蘭亭風(fēng)雨
總結(jié)
以上是生活随笔為你收集整理的Java并发编程(7):使用synchronized获取互斥锁的几点说明的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java并发编程(6):Runnable
- 下一篇: Java并发编程(8):多线程环境中安全