多線程之JUC筆記

JUC并發(fā)包是jdk提供的一系列關(guān)于并發(fā)框架的jar包,最基本的有Lock和Condition,對(duì)應(yīng)sychronized和wait&notify的功能,其核心是AQS抽象隊(duì)列同步器。

AQS

AQS抽象隊(duì)列同步器維護(hù)著一個(gè)FIFO阻塞同步隊(duì)列,還有一個(gè)內(nèi)部類(lèi)ConditionObject,一個(gè)FIFO等待隊(duì)列,它們的基本數(shù)據(jù)結(jié)構(gòu)都是一個(gè)Node類(lèi)。Node主要有prev,next,nextWaiter,waitStatus這些屬性。此外還有一個(gè)state記錄鎖次數(shù),owner記錄當(dāng)前獲取鎖的線程。下面以Reentrantlock來(lái)分析具體過(guò)程。

lock()

首先會(huì)使用cas操作嘗試更新state=1,若成功表明未有線程獲取鎖,設(shè)置當(dāng)前線程為owner,線程繼續(xù)執(zhí)行。若更新失敗表示已有其他線程獲取到鎖,將當(dāng)前線程包裝為一個(gè)Node,并cas設(shè)置waitStatus為-1(Node.Singal)放入AQS隊(duì)列尾部(若head為空,則新建一個(gè)Node節(jié)點(diǎn)作為head),設(shè)置prev和next。然后自旋對(duì)這個(gè)Node嘗試獲取鎖,成功則將此Node設(shè)為head,前一個(gè)節(jié)點(diǎn)的next設(shè)為null幫助gc回收,失敗則park當(dāng)前線程使之阻塞。

unlock()

使state減1,若state為0表明鎖已全部釋放完。獲取AQS結(jié)點(diǎn)中的頭結(jié)點(diǎn)的下一節(jié)點(diǎn),喚醒其中線程,則喚醒此時(shí)被park的線程繼續(xù)自旋獲取到鎖。如果是共享模式則在自旋設(shè)置head之后多執(zhí)行了一步操作,繼續(xù)喚醒后續(xù)共享模式結(jié)點(diǎn)中的線程。

await()

必須在當(dāng)前線程獲取鎖時(shí)才能執(zhí)行,首先把當(dāng)前線程構(gòu)成一個(gè)Node,設(shè)置waitStatus為-2(Node.CONDITION)并放入ConditionObject隊(duì)列尾部。然后對(duì)當(dāng)前線程完全釋放鎖,喚醒AQS中的頭部線程,隨后park當(dāng)前線程。

singal()&singalAll()

取ConditionObject隊(duì)列首部節(jié)點(diǎn),并把它從隊(duì)列中移除,CAS將Node的waitStatus從CONDITION置為0,隨后放入AQS隊(duì)列的尾部,再設(shè)置waitStatus從CONDITION置為-1,unpark喚醒這個(gè)線程。

CAS操作

CAS比較交換是一種樂(lè)觀鎖機(jī)制,其過(guò)程是取當(dāng)前值和預(yù)期值進(jìn)行比較,若一致,則將更新值作為最新值,不一致則操作失敗,它是一種cpu指令級(jí)別的原子操作,且是直接根據(jù)內(nèi)存中的地址來(lái)做對(duì)比更新。

park&unpark

park&unpark底層原理是獲取一個(gè)許可&給予一個(gè)許可,在jvm中每個(gè)線程有一個(gè)Parker實(shí)例,其中有個(gè)_counter變量來(lái)記錄是否有許可。
1.unpark時(shí)先更新_counter為1,并判斷之前的_counter小于1;
如果小于1,則去喚醒阻塞的線程,若有線程被喚醒然后使_counter為0;
如果給定線程沒(méi)有啟動(dòng)start,則該操作沒(méi)有任何效果.
2.park,則會(huì)檢測(cè)_counter是否大于0;
如果大于0則將_counter變成0,線程繼續(xù)執(zhí)行,否則堵塞線程。
3.線程被park后阻塞時(shí),如果被中斷也會(huì)被喚醒。

JUC并發(fā)工具包

1.Semaphore 信號(hào)量是一類(lèi)經(jīng)典的同步工具。信號(hào)量通常用來(lái)限制線程可以同時(shí)訪問(wèn)的(物理或邏輯)資源數(shù)量。

2.CountDownLatch閉鎖 一種非常簡(jiǎn)單、但很常用的同步輔助類(lèi)。其作用是在完成一組正在其他線程中執(zhí)行的操作之前,允許一個(gè)或多個(gè)線程一直阻塞。CountDownLatch閉鎖狀態(tài)包括一個(gè)計(jì)數(shù)器,該計(jì)數(shù)器被初始化為一個(gè)正數(shù),表示需要等待的事件數(shù)量。countDown方法將遞減計(jì)數(shù)器,表示有一個(gè)事件已經(jīng)發(fā)生了,而await方法等待計(jì)數(shù)器到達(dá)零,這表示所有需要的事件都已經(jīng)發(fā)生。如果計(jì)數(shù)器的值為非零,那么await會(huì)一直阻塞直到計(jì)數(shù)器為零,或者等待中的線程中斷,或者等待超時(shí)。

3.CyclicBarrier柵欄類(lèi)似于閉鎖,它能阻塞線程直到某個(gè)事件發(fā)生。當(dāng)線程到達(dá)柵欄位置時(shí),將調(diào)用await方法,這個(gè)方法將阻塞直到所有線程都到達(dá)阻塞位置。如果所有線程都到達(dá)了柵欄的位置,那么柵欄將打開(kāi),此時(shí)所有線程都將被釋放,而柵欄將被重置以便下次使用。如果對(duì)await的調(diào)用超時(shí),或者await阻塞的線程被中斷,那么柵欄就被認(rèn)為是打破了,所有阻塞的await調(diào)用都將終止并拋出BrokenBarrierException。如果成功地通過(guò)柵欄,那么await將為每個(gè)線程返回一個(gè)唯一的到達(dá)索引號(hào),我們可以利用這些索引來(lái)“選舉”產(chǎn)生一個(gè)領(lǐng)導(dǎo)線程,并在下一次迭代中由該領(lǐng)導(dǎo)線程執(zhí)行一些特殊的工作。
柵欄與閉鎖的關(guān)鍵區(qū)別在于:所有線程必須同時(shí)到達(dá)柵欄位置,才能繼續(xù)執(zhí)行。而且閉鎖只能使用一次,而柵欄可以重復(fù)循環(huán)使用。

4.JDK1.7中的Phaser一種可重用的同步屏障,功能上類(lèi)似于CyclicBarrier和CountDownLatch,但使用上更為靈活。CountDownLatch和CyclicBarrier都是只適用于固定數(shù)量的參與者,Phaser適用于可變數(shù)目的屏障。

5.JDK1.8中的StampedLock,優(yōu)化了之前的讀寫(xiě)鎖ReentrantReadWriteLock。讀寫(xiě)鎖特點(diǎn)是讀-讀不互斥(Node設(shè)置為共享模式),讀-寫(xiě)互斥,寫(xiě)-寫(xiě)互斥,本質(zhì)上來(lái)說(shuō)都是悲觀鎖。StampedLock在將讀鎖優(yōu)化成了一種樂(lè)觀鎖機(jī)制,而對(duì)于讀-寫(xiě)的情況,在讀的時(shí)候會(huì)判斷是否有寫(xiě)操作,有則再讀一次。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,870評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,742評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,527評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,010評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,250評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,656評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,853評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,103評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,472評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,717評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,487評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,815評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容