深入多線程之:用Wait與Pulse模擬一些同步構(gòu)造的應(yīng)用詳解
你可能在上篇文章中《深入多線程之:雙向信號與競賽的用法分析》注意到了這個模式:兩個Waiting 循環(huán)都要下面的構(gòu)造:
lock(_locker)
{
while(!_flag) Monitor.Wait(_locker);
_flag = false;
}
在這里_flag被另一線程設(shè)置為true。這是,從作用上講,這里在模仿AutoResetEvent。如果我們將 _flag = false;去掉,那么我們就得到了一個基本的ManualResetEvent.
讓我們使用Wait和Pulse來為ManualResetEvent完成剩余的代碼吧。
readonly object _locker = new object();
bool _signal;
void WaitOne()
{
lock (_locker)
{
while (!_signal) Monitor.Wait(_locker);
}
}
void Set()
{
lock (_locker) { _signal = true; Monitor.PulseAll(_locker); }
}
void Reset() { lock (_locker) _signal = false; }
在這里使用PulseAll,是因為可能有很多阻塞的線程。
如果在WaitOne方法中增加_signal=false就可以簡單的模擬AutoResetEvent.例如:
void WaitOne()
{
lock (_locker)
{
while (!_signal) Monitor.Wait(_locker);
_signal = false; //實現(xiàn)自動關(guān)閉功|能
}
}
然后在Set方法中,將PulseAll修改為Pulse
Lock(_locker) {_signal = true; Monitor.Pulse(_locker);}
如果使用的是int類型的_signal 標(biāo)志,那么我們可以得到一個最基本的Semaphore.
Waiting Queues and PulseAll
當(dāng)多余一個線程在同一個對象上面等待的時候,一個 “等待隊列(waiting queue)” 就形成了。
每一次調(diào)用Pulse都會釋放在”等待隊列”頭部的一個線程。下面的圖形象的展示了這一點:

線程調(diào)用Monitor.Enter 進(jìn)入ReadyQueue. 等待獲取鎖,成功獲取鎖后,如果正常的執(zhí)行,那么之后會調(diào)用Monitor.Exit退出,
否則如果獲取了鎖之后發(fā)現(xiàn)需要等待其他的線程或者是其他阻塞條件,那么調(diào)用Wait方法,就進(jìn)入了等待隊列,
當(dāng)?shù)却木€程完成并調(diào)用Pulse后,處在WaitingQueue頭部的線程就被 Pulse了,等待CPU調(diào)度 。之后再次進(jìn)入Ready Queue,重新獲取鎖。
Countdown
借助Wait和Pulse,我們可以實現(xiàn)CountdownEvent的主要功能。例如:
class Countdown
{
object _locker = new object();
int _value; //使用_value來計數(shù)
public Countdown() { }
public Countdown(int initialCount) { _value = initialCount; }
public void Singnal() { AddCount(-1); } //將計數(shù)減一
public void AddCount(int amount)
{
lock (_locker)
{
_value += amount; //將計數(shù)增加或減少
if (_value <= 0) Monitor.PulseAll(_locker);//如果value<=0,說明所有等待的任務(wù)都完成了。
}
}
public void Wait()
{
lock (_locker)
{
//只要計數(shù) > 0 就等待。
while (_value > 0)
{
Monitor.Wait(_locker);
}
}
}
}
這和我們上次的代碼幾乎一致,只是這次我們的阻塞條件基于一個整型_value標(biāo)志。
相關(guān)文章
C#實現(xiàn)Json轉(zhuǎn)Unicode的方法
這篇文章主要介紹了C#實現(xiàn)Json轉(zhuǎn)Unicode的方法,可實現(xiàn)輸入為帶有json格式的文本,輸出正常文本的功能,需要的朋友可以參考下2014-09-09
C#自定義導(dǎo)出數(shù)據(jù)到Excel的類實例
這篇文章主要介紹了C#自定義導(dǎo)出數(shù)據(jù)到Excel的類,實例分析了C#操作Excel的技巧,非常具有實用價值,需要的朋友可以參考下2015-03-03
深入學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程(上)
這篇文章主要介紹了如何學(xué)習(xí)C#網(wǎng)絡(luò)編程之HTTP應(yīng)用編程的相關(guān)知識,文中講解的非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-06-06

