多執行緒分析之Semaphore

2022-03-31 19:05:48 字數 3242 閱讀 4659

網上看了許多講解semaphore的,用semaphore來實現順序列印字母,但是可能大家都沒有清楚具體的原因,所以來給大家分析下為什麼可以使用semaphore來實現順序列印字母順序。

先開啟jdk8原始碼中的semaphore,可以看到semaphore是通過繼承aqs來現實功能(aqs,doug lea大神重寫並發包的核心,這個預設自己看過哈,其實蠻簡單,核心原理:通過模板方法,完成流程呼叫,讓子類實現具體方法,然後實現不同功能)。

說正事,我們貼出一張semaphore的層級關係圖。

在semaphore中主要是sync類實現abstractqueuedsynchronizer,然後sync又有兩個實現類,分別是fairesync和nonfairsync,即公平鎖和非公平鎖。我們來看下sync中的部分原始碼:

/**

* synchronization implementation for semaphore. uses aqs state

* to represent permits. subclassed into fair and nonfair

* versions. (使用aqs的state變數來代表許可,注釋這段還是蠻重要)

*/abstract static class sync extends abstractqueuedsynchronizer

// 獲取許可數量

final int getpermits()

// 非公平鎖獲取許可方式

final int nonfairtryacquireshared(int acquires)

}// 歸還許可,更新可用許可數量

protected final boolean tryreleaseshared(int releases)

}// 減少許可, 獲取時需要減少許可數量

final void reducepermits(int reductions)

}}

在類中,沒有特別難的方法,都是都過cas來進行操作,用aqs中的state來當作許可。好了, 有了這一部分基礎,我們可以去看看大家是如何使用semaphore來實現順序列印的。還是先為大家貼上**:

/**

* 使用訊號量順序列印

* *

@author

lifacheng

* @version

1.0 * @date 2019/6/18 11:08

* @since

1.0

*/public

class

thread11

} catch

(exception e) }};

t2 = new

thread()

} catch

(interruptedexception e) }};

}public

void

run()

public

static

void main(string args) throws

exception

}

在**一開始,初始化了兩個訊號量,分別為:semaphore1,semaphore2,semaphore1的許可書為0個,semaphore2的許可書為1個。

acquire()原始碼分析

**呼叫了sync中的acquiresharedinterruptibly()方法,此時我們要注意,傳入的引數是1個(這個很重要)。我們接著往下找,找到這個是aqs中實現的方法。

我們找到具體的實現類中的方法,即tryacquireshare(arg)這個在semaphore中實現的方法。(在tryacquireshare(arg)<0時,會進去doacquiresharedinterruptibly()方法中,當獲取小於0會處於阻塞狀態)

我們可以看到有semaphore有兩個實現類,分別是公平和非公平兩種實現,我們點進去看看到底有何不同。

公平:

非公平:

我們看到,公平就比非公平多了乙個判斷,這個判斷就是判斷是否是頭節點(就不點進去看了哈)。

至此,我們可以看到,acquire()方法具體實現就是獲取了乙個許可。我們接著看**,然後輸出字元a,semaphore1執行了release()方法。

release()方法分析

我們點進release方法檢視,

按照和acquire()的相同的邏輯,最後找到如上這段**,即在執行release()方法時,會增加1個許可。

**邏輯

自此我們知道**的邏輯了,來具體分析下**。

當執行緒t1和t2同時開始執行,這個t1開始執行獲取到許可,然後輸出a,這是就算t2拿到cpu執行權,由於初始化許可數為0,這時acquire()方法獲取不到許可,處於阻塞狀態。只有當t1中的semaphore1執行了release()方法時,才會增加乙個許可,t2獲取到cpu執行權後才會執行。假設此時t1又獲取到cpu執行權,但是由於只有乙個許可,開始獲取過許可,再此獲取會失敗,也會處於阻塞狀態,只有t2執行緒中semaphore2執行了release()方法才會增加乙個許可,然後t1才會再次獲取成功並執行。

**充分使用了許可數量來控制線程的執行,當執行緒執行時,相互喚醒,增加許可數量。有點像wait和notify的概念,但是更高階,我們可以增加semaphore來控制多個執行緒執行順序。 這下次就分析清楚了,為什麼初始化0個許可數的semaphore仍然可以用來控制。可以說相當神奇。我們也對aqs的強大有了乙個小小的了解。

aqs的強大一時半會說不清楚,希望大家多看看原始碼,結合百家之所長,來提公升自己。

c 多執行緒 Semaphore

訊號量說簡單點就是為了執行緒同步,或者說是為了限制執行緒能執行的數量。那它又是怎麼限制執行緒的數量的哩?是因為它內部有個計數器,比如你想限制最多5個執行緒執行,那麼這個計數器的值就會被設定成5,如果乙個執行緒呼叫了這個semaphore,那麼它的計數器就會相應的減1,直到這個計數器變為0。這時,如果...

執行緒同步之Semaphore

之前和大家分享過countdownlatch和cyclicbarrier 相關鏈結 下面說個場景,例如我有乙個資源,只想讓2個執行緒訪問,當乙個執行緒釋放了資源,其他執行緒才可以有機會訪問這個資源,這樣的場景用之前的執行緒同步工具好像都不太好使,所以這裡給大家介紹乙個新的工具semaphore,廢話...

C 多執行緒同步之Semaphore 訊號量

一 當多個執行緒對同一資源進行使用時,會產生 爭奪 的情況,為了避免這種情況的產生,也就出現了執行緒間的同步這個技術,本篇博文中將介紹使用訊號量semaphore達到執行緒間同步的目的。二 相關函式和標頭檔案 標頭檔案 include 建立訊號量api handle winapi createsem...