當前位置:編程學習大全網 - 源碼下載 - J.U.C鎖之 Semaphore

J.U.C鎖之 Semaphore

Semaphore 名為"信號量"。

Semaphore用來管理內部許可證,當多個線程要訪問競爭資源時可以通過Semaphore來控制並發訪問競爭資源的線程數。當線程需要訪問競爭資源時需要首先獲取壹個許可證,執行完畢在返還,如果許可證用完則,線程進入同步隊列並阻塞。等待許可證返回喚醒。

主要特性

公平性 :支持公平性和非公平性。所謂公平表示在獲取鎖時邏輯是否要考慮當前正在排隊等待線程。按照大白話來說就時公平表示不能插入強占資源。

應用場景

獲取許可

釋放許可

其他方法

Semaphore 使用AQS實現鎖機制,AQS是AbstractQueuedSynchronizer的縮寫,翻譯過來就是"同步器",,它實現了Java函數中鎖同步(synchronized),鎖等待(wait,notify)功能。

AbstractQueuedSynchronizer是壹個抽象類,我們可以編寫自己類繼承AQS重寫獲取獨占式或***享式同步狀態模板方法,實現鎖鎖同步(synchronized),鎖等待(wait,notify)功能

AQS核心是壹個同步狀態,兩個隊列。它們實現了Java函數中鎖同步(synchronized),鎖等待(wait,notify),並在其基礎上實現了獨占式同步,***享式同步2中方式鎖的實現。

無論獨占式還時***享式獲取同步狀態成功則直接返回,失敗則進入CLH同步隊列並阻塞當前線程。當獲取同步狀態線程釋放同步狀態,AQS會選擇從CLH隊列head頭部節點的第壹個節點釋放阻塞,嘗試重寫競爭獲取同步狀態,如果成功則將當前節點出隊。如果失敗則繼續阻塞。

獲取同步狀態的線程也可以使用condition對象釋放同步狀態進入等待隊列。只有等待其他線程使用condition.signal或condition.signAll()喚醒被從阻塞狀態中釋放重新競爭獲取同步狀態成功後從原來指令位置繼續運行。

AQS實現了鎖,必然存在壹個競爭資源。AQS存在從壹個int類型的成員變量state,我們把它稱為同步狀態,同步狀態通常用做判斷線程能否獲取鎖的依據

AQS 實現了鎖那麽總需要壹個隊列將無法獲取鎖的線程保存起來,方便在鎖釋放時通知隊列中線程去重新競爭鎖。

實現原理

同步隊列又被稱為CLH同步隊列,CLH隊列是通過 鏈式方式實現FIFO雙向隊列 。當線程獲取同步狀態失敗時,AQS則會將當前線程構造成壹個節點(Node)並將其加入到CLH同步隊列,同時會阻塞當前線程,當同步狀態被釋放時,會把首節點後第壹個節點的線程從阻塞狀態下喚醒,喚醒的線程會嘗試競爭同步狀態,如果能獲取同步狀態成功,則從同步隊列中出隊。

實現原理

這裏取消節點表示當前節點的線程不在參與排隊獲取鎖。

從概念上來說獨占式對應只存在壹個資源,且只能被壹個線程或者說競爭者占用.

從概念上來說***享式對應存在多個資源的是有多個線程或者競爭者能夠獲取占用.

我們可以編寫自己類繼承AQS選擇重寫獨占式或***享式模板方法,從而定義如何獲取同步狀態和釋放同步狀態的邏輯。

tryAcquire :嘗試獨占式獲取同步狀態,返回值為true則表示獲取成功,否則獲取失敗。

tryRelease

嘗試獨占式釋放同步狀態,返回值為true則表示獲取成功,否則獲取失敗。

tryAcquireShared :嘗試***享式獲取同步狀態,當返回值為大於等於0的時獲得同步狀態成功,否則獲取失敗。

tryReleaseShared :嘗試***享式釋放同步狀態,返回值為true則表示獲取成功,否則獲取失敗。

由於多個線程可以同時許可同時執行,當然我們選擇使用***享同步,Sync需要重寫 tryAcquire 獲取同步狀態條件邏輯, tryRelease 釋放同步條件邏輯。其核心點在於使用同步狀態做判斷。當同狀態為0時,許可被使用完了,同步狀態大於0,許可被還可用,每次調用 tryAcquire 同步狀態-1,每次調用 tryRelease 同步狀態+1

內部存在有三個內部類 Sync、NonfairSync 和 FairSync 類。

Semaphore 很多方法都通過代理內部類的方法實現。

公平信號量獲取許可

非公平信號量獲取許可

釋放許可

完整源碼

  • 上一篇:越來越多人不敢吃海鮮,海鮮市場該如何把控?
  • 下一篇:通達OA的通達OA全面解讀
  • copyright 2024編程學習大全網