天天看點

多線程-3(同步)

SemaphoreSlim類

代碼:

View Code

多線程-3(同步)

 主線程啟動,建立SemaphoreSlim的一個執行個體,在構造函數中指定允許并發線程數量,啟動6個不同名稱和不同初始運作時間的線程,借助信号系統限制通路資料的并發數, 隻允許4個線程擷取, 注意:.當線程1完成後,線程0才進行授權通路。

AutoResetEven類

多線程-3(同步)

AutoResetEvent類采用的是核心時間模式,是以等待時間不能太長。使用ManualResetEventslim類更好。

ManualResetEventSlim類

static ManualResetEventSlim mainEvent = new ManualResetEventSlim(false);

static void TravleThroughGates(string threadName,int seconds)

{

Console.WriteLine("{0} falls to sleep",threadName);

Thread.Sleep(TimeSpan.FromSeconds(seconds));

Console.WriteLine("{0} waits for the gates to open!",threadName);

mainEvent.Wait();//

Console.WriteLine("{0} enters the gates!", threadName);

}

static void Main(string[] args)

var t1 = new Thread(() => TravleThroughGates("threadName 1", 5));

var t2 = new Thread(() => TravleThroughGates("threadName 2", 6));

var t3 = new Thread(() => TravleThroughGates("threadName 3", 12));

t1.Start();

t2.Start();

t3.Start();

Thread.Sleep(TimeSpan.FromSeconds(6));

Console.WriteLine("The gates are now open!");

mainEvent.Set();//

Thread.Sleep(TimeSpan.FromSeconds(2));

mainEvent.Reset();//将事件狀态設定為非終止,進而導緻線程受阻

Console.WriteLine("The gates have been closed!");

Thread.Sleep(TimeSpan.FromSeconds(10));

Console.WriteLine("The gates are now open for the seconds time!");

mainEvent.Set();

mainEvent.Reset();

這裡啟動了三個線程,同時進行等待。ManualResetEventSlim 的set是允許準備好的線程接受信号并繼續工作。

CountDownEvent類

CountDownEvent信号類來等待直到一定數量的操作完成。

static CountdownEvent countdownEvent = new CountdownEvent(2);

static void PerformOperation(string message,int seconds)

Console.WriteLine(message);

countdownEvent.Signal();

Console.WriteLine("Starting two operations");

var t1 = new Thread(() => PerformOperation("Operation 1 is completd", 4));

var t2 = new Thread(() => PerformOperation("Operation 2 is completd", 8));

countdownEvent.Wait();

Console.WriteLine("Both operation have been completd");

countdownEvent.Dispose();

多線程-3(同步)

啟動兩個線程,當它們執行完成後會發生信号。一旦第二個線程完成,主程式會從等待CountdownEvent的狀态中傳回并繼續執行。當針對需要等待多個異步操作的情形,方法非常周遊。當然如果某個線程出現死鎖等情況,一直等待下,那麼會一直等待。

Barrier類

Barrier類組織多個線程及時在某個時刻碰面。并提供了一個回調函數,每次線程調用了SignalAndWait方法後該回調函數會執行

static Barrier barrier = new Barrier(2, b => Console.WriteLine("End of phase {0}", b.CurrentPhaseNumber + 1));

static void PlayMusic(string name,string messages,int seconds)

for (int i = 0; i < 3; i++)

{

Console.WriteLine("-----------------------------");

Thread.Sleep(TimeSpan.FromSeconds(seconds));

Console.WriteLine("{0} starts to {1}", name, messages);

Console.WriteLine("{0} finshes to {1}", name, messages);

barrier.SignalAndWait();

}

var t1 = new Thread(() => PlayMusic("the guitarist", "play an amazing solo", 5));

var t2 = new Thread(() => PlayMusic("the singer", "sing his song", 2));

使用Barrier,指定我們想同步兩個線程。這兩個線程任意一個調用了SignalAndWait方法後,會執行一個回調來列印出階段

多線程-3(同步)

ReaderWriterLockSlim

ReaderWriterLockSlim類來建立一個線程安全的機制,在多線程中對一個集合進行讀寫操作。ReaderWriterLockSlim代表一個管理資源通路的鎖,允許多個線程同時讀取,以及獨占寫。

多線程-3(同步)

同時運作了三個程式來從字典中讀取資料,還有另外兩個線程向該字典中寫入資料,使用ReaderWriterLockSlim類實作線程安全。

這裡使用兩種鎖:讀鎖允許多線程讀取資料,寫鎖在被釋放前會阻塞了其他線程的所有操作,先擷取讀鎖後讀取資料,如果發現必須修改底層集合,隻需使用EnterWriterLock方法更新鎖,然後快速執行寫操作。

SpanWait類

如果不使用核心模型的方式來使線程等待。SpanWait是一個混合同步結構,設計為使用使用者模式等待一段時間,然後切換到核心模式以節省CPU時間

static volatile bool isCompleted = false;//volatile允許多個線程通路,呈現最新的

static void UserModelWait()

while(!isCompleted)

Console.WriteLine(".");

Console.WriteLine("Waiting is complete");

static void HybridSpinWait()

var w = new SpinWait();

while (!isCompleted)

w.SpinOnce();

Console.WriteLine(w.NextSpinWillYield);

var t1 = new Thread(UserModelWait);

var t2 = new Thread(HybridSpinWait);

Console.WriteLine("Running user mode waiting");

Thread.Sleep(20);

isCompleted = true;

Thread.Sleep(TimeSpan.FromSeconds(1));

isCompleted = false;

Console.WriteLine("Running hybrid SpinWait construct waiting");

Thread.Sleep(5);

多線程-3(同步)

定義一個線程,将執行一個無止境的循環,直到20毫秒後主線程設定isCompleted變量為true,我們可以試驗周期為20-30秒,通過windows任務管理器測量CPU的負載情況。

用volatie關鍵字來聲明iscompleted靜态字段,volatie字段不會被編輯器和處理器優化,隻能被單個線程通路。

繼續閱讀