Thread同步 鎖 訊號量

2021-07-31 17:38:16 字數 3603 閱讀 4169

一、鎖monitor(控制每個執行緒之間通訊的執行順)

1. monitor(控制線程間通訊順序)

說到鎖的時候通常都會想到lock,lock確實減少了我們不必要的勞動並且讓**更可觀,但是如果我們要進行控制每個執行緒之間通訊的執行順序,則必須使用原生類,這裡要注意乙個問題就是「鎖住什麼」的問題,一般情況下我們鎖住的都是靜態物件,我們知道靜態物件屬於類級別,當有很多執行緒共同訪問的時候,那個靜態物件對多個執行緒來說是乙個,不像例項欄位會被認為是多個。

這裡主要介紹monitor類主要是鎖定的臨界區中只允許讓乙個執行緒訪問,其他執行緒排隊等待

monitor.enter()獲取指定物件上的排他(鎖住指定物件在當前執行緒訪問期間,其他物件無法訪問)

monitor.wait()暫時的釋放資源鎖,然後該執行緒進入」等待佇列「中,那麼自然別的執行緒就能獲取到資源鎖

monitor.pulse()喚醒「等待佇列」中的執行緒,那麼當時被wait的執行緒就重新獲取到了鎖

monitor.exit()釋放指定物件上的排他鎖(釋放鎖住的物件允許其他物件訪問)

看如下**:

static void main(string args)

public static void run1()

public static void run2()

允許結果:

readerwriterlock(實現多使用者讀/單使用者寫同步)

c#提供了system.threading.readerwriterlock類以適應多使用者讀/單使用者寫的場景。該類可實現以下功能:如果資源未被寫操作鎖定,那麼任何執行緒都可對該資源進行讀操作鎖定,並且對讀操作鎖數量沒有限制,即多個執行緒可同時對該資源進行讀操作鎖定,以讀取資料。

用monitor或mutex進行同步控制的問題:由於獨佔訪問模型不允許任何形式的併發訪問,這樣的效率總是不太高。許多時候,應用程式在訪問資源時是進行讀操作,寫操作相對較少。為解決這一問題,c#提供了system.threading.readerwriterlock類以適應多使用者讀/單使用者寫的場景。該類可實現以下功能:如果資源未被寫操作鎖定,那麼任何執行緒都可對該資源進行讀操作鎖定,並且對讀操作鎖數量沒有限制,即多個執行緒可同時對該資源進行讀操作鎖定,以讀取資料。如果資源未被新增任何讀或寫操作鎖,那麼乙個且僅有乙個執行緒可對該資源新增寫操作鎖定,以寫入資料。簡單的講就是:讀操作鎖是共享鎖,允許多個執行緒同時讀取資料;寫操作鎖是獨佔鎖,同一時刻,僅允許乙個執行緒進行寫操作。

看下面**:

public

class wirtereadlockhelper

//讀資料

static

void read()

", intcount);

thread.sleep(10);

console.writeline("讀取資料結束,我讀取的資料是:", intcount);

//釋放讀操作鎖

rwl.releasereaderlock();

}//寫資料

static

void write()

", intcount);

//將theresource加1

intcount++;

thread.sleep(100);

console.writeline("寫資料結束,我讀取的資料是:", intcount);

//釋放寫操作鎖

rwl.releasewriterlock();}}

執行結果:

觀察執行結果,我們很容易看出:讀操作鎖是共享鎖,允許多個執行緒同時讀取資料;寫操作鎖是獨佔鎖,僅允許乙個執行緒進行寫操作。

如果乙個執行緒在獲取讀操作鎖後,進行讀操作的途中,希望提公升鎖級別,將其變為寫操作鎖,可以呼叫readerwriterlock類的upgradetowriterlock(int timeout)方法,該方法返回乙個lockcookie值,該值儲存了upgradetowriterlock方法呼叫前線程鎖的狀態。待寫操作完成後,可呼叫downgradefromwriterlock(lockcookie lockcookie)方法,該方法根據傳入的lockcookie引數值,將執行緒鎖恢復到upgradetowriterlock方法呼叫前的狀態。

二、訊號量(semaphore控制線程執行的數量)

訊號量(semaphore)是由核心物件維護的int變數,當訊號量為0時,在訊號量上等待的執行緒會堵塞,訊號量大於0時,就解除堵塞。當在乙個訊號量上等待的執行緒解除堵塞時,核心自動會將訊號量的計數減1。在.net 下通過semaphore類來實現訊號量同步。

semaphore類限制可同時訪問某一資源或資源池的執行緒數。執行緒通過呼叫 waitone方法將訊號量減1,並通過呼叫 release方法把訊號量加semaphore類中重要方法有:

semaphore(int initialcount, int maximumcount)該方法是訊號量的建構函式initialcount訊號量初始化時預設能夠允許執行的執行緒數量,maximumcount表示該訊號量能夠允許執行執行緒的最大數量

semaphore.waitone();當執行緒呼叫的方法中新增了該waitone(執行緒阻塞)的方法時,那麼執行的執行緒數量超過訊號量初始化時預設的執行緒數量時,超過的執行緒數量就會發生堵塞不在執行,當呼叫release方法時傳入的引數就是釋放掉的訊號量(也就是說訊號量在初始化的時候預設執行執行緒的數量的基礎上還能夠允許執行的執行緒數量)

semaphore.release(releasecount) 當呼叫release方法時傳入的引數就是釋放掉的訊號量(也就是說訊號量在初始化的時候預設執行執行緒的數量的基礎上還能夠允許執行的執行緒數量)

看下面**:

// 初始訊號量計數為5,最大計數為9  

//semaphore(int initialcount, int maximumcount)

//initialcount表示該訊號量預設執行執行緒數量

public

static semaphore semaphore = new semaphore(5,9);

public

static

int time = 0;

static

void main(string args)

// 等待1秒讓所有執行緒開始並阻塞在訊號量上

thread.sleep(1000);

// 訊號量計數加2

// 最後可以看到輸出結果次數為7次

semaphore.release(2);

console.read();

}public

static

void

testmethod(object number)

run ", number);

}

允許結果:

同步 訊號量

include stdafx.h include includeusing namespace std int number 1 定義全域性變數 handle hsemaphore 定義訊號量控制代碼 unsigned long stdcall threadproc1 void lp long co...

執行緒訊號量同步

thread sem.c include include include include define thread number 3 define repeat number 3 define delay time levels 10.0 sem t sem thread number void ...

同步和訊號量

下面介紹用訊號量進行同步。訊號量概念由荷蘭科學家dijkstra首先提出。訊號量是乙個特殊型別的變數,它可以被增加或者減少。但對其的關鍵訪問被保證是原子操作,即使在乙個多執行緒程式中也是如此。訊號量有兩種型別 1 二進位制訊號量。它只有0和1兩種取值。2 計數訊號量。它可以有更大的取值範圍。如果要用...