Java併發包下鎖學習第二篇Java併發基礎框架-隊列同步器介紹

Java併發包下鎖學習第二篇隊列同步器

還記得在第一篇文章中,講到的locks包下的類結果圖嗎?如下圖:


Java併發包下鎖學習第二篇Java併發基礎框架-隊列同步器介紹

從圖中,我們可以看到AbstractQueuedSynchronizer這個類很重要(在本文中,凱哥就用AQS來代替這個類)。我們先來了解這個類。對這個類瞭解之後,學習後面的會更容易了。

本篇是《凱哥(凱哥Java:kagejava)併發編程學習》系列之《Lock系列》教程的第一篇:《Java併發包下鎖學習第二篇:隊列同步器》。

本文主要內容:同步器介紹;同步器和鎖的關係;AQS對象構成。

一:隊列同步器

AQS是創建鎖或者是同步組件的基礎框架,其內部維護了一個FIFO隊列來維護線程對資源獲取的順序。

定義了若干同步狀態獲取和釋放的方法來供自定義組件使用。如果獲取狀態(getStatus())、設置狀態(setStatus())以及使用CAS設置當前線程狀態來確保原子性的。這種設計思想是基於模板方法模式來設計的。使用者(或子類)需要繼承同步器並重寫方法。

因為同步器支持獨佔式獲取當前線程狀態,也支持共享式的獲取這個同步狀態,所以這樣就可以實現不同類型的組件了。如以獨佔式獲取鎖的ReentrantLock和以共享式獲取的ReentrantReadWriteLock。需要說明的是:在一個同步組件中只能以一種方式獲取鎖。要麼是獨佔式要麼是共享式。

同步器主要是以繼承關係,子類實現父類抽象方法來管理自己類中線程狀態的。從源碼(後面學習中,我們將查看源碼)中我們可以看出,推薦子類常常被定義為自定義組件的靜態內部類來實現的。

二:同步器和鎖之間的關係

同步器是鎖(或者是其他同步組件)實現的關鍵;

鎖和同步器定義所面向的對象不同

可以理解為鎖是面向開發者(程序員)也即是鎖的使用者而言的。鎖定義了開發者在調用時候鎖的交互接口(如獨享方式的鎖頂級接口lock),隱藏了鎖具體實現的細節。如我們在使用Lock的時候,只需要lock.lock()獲取鎖,然後使用lock.unlock()釋放鎖就可以了。具體怎麼獲取鎖,怎麼釋放鎖的操作在內部實現的。使用者不用關心具體實現的細節。

同步器是面向鎖的實現類的。如Lock接口的實現類ReentrantLock其內部Sync內部類就是同步器的實現類。同步器簡化了鎖的實現方式。如對同步狀態管理、多個線程排隊管理以及線程之間等待與喚醒等這些底層的操作。

可以說,鎖和同步器很好的隔離了使用者和實現者所關注的領域。使用者只關心怎麼獲取/釋放鎖;實現者關心同步狀態、排隊等操作的實現。

三:AQS對象構成

為什麼會寫AQS的構成呢?我們想要徹底的瞭解獨佔式鎖和共享鎖離不開這個對象。所以咱們先來把這個對象搞清楚,然後再學習後面的就方便了。

內部類:Node

在上文中,我們說到,AQS內部是維護了一個FIFO的隊列來保證獲取鎖的線程排隊的。這個對象就是Node。在下一篇文章中,凱哥將帶著大家一起解讀源碼,從源碼中詳細講解Node內部類及鏈表是具體怎麼工作的,怎麼來維護隊列實現FIFO的。歡迎繼續學習下一篇文章

內部類:CoditionObject

操作線程之間的等待/通知模式的類。其功能和Object的wait()、wait(long time) 、notify()及notifyAll()這些方法類似。但又有不同。在後面文章中,凱哥也會講解的。

常用的API方法

常用的方法。如獨佔式獲取鎖、獲取同步狀態、獨佔式釋放鎖;共享式模式下怎麼獲取鎖、怎麼獲取同步狀態及怎麼釋放鎖;怎麼阻塞線程及怎麼喚醒線程。這些常用的方法。凱哥在後文中也會詳細介紹的。

在接下來的幾篇文章中,凱哥將帶著大家一起擼碼AQS的源碼一點一點分析。搞懂鎖(或其他同步組件)的基礎框架-同步器。歡迎大家接著學習後面文章。


分享到:


相關文章: