SemaphoreSlim類
代碼:
View Code
主線程啟動,建立SemaphoreSlim的一個執行個體,在構造函數中指定允許并發線程數量,啟動6個不同名稱和不同初始運作時間的線程,借助信号系統限制通路資料的并發數, 隻允許4個線程擷取, 注意:.當線程1完成後,線程0才進行授權通路。
AutoResetEven類
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();
啟動兩個線程,當它們執行完成後會發生信号。一旦第二個線程完成,主程式會從等待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方法後,會執行一個回調來列印出階段
ReaderWriterLockSlim
ReaderWriterLockSlim類來建立一個線程安全的機制,在多線程中對一個集合進行讀寫操作。ReaderWriterLockSlim代表一個管理資源通路的鎖,允許多個線程同時讀取,以及獨占寫。
同時運作了三個程式來從字典中讀取資料,還有另外兩個線程向該字典中寫入資料,使用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);
定義一個線程,将執行一個無止境的循環,直到20毫秒後主線程設定isCompleted變量為true,我們可以試驗周期為20-30秒,通過windows任務管理器測量CPU的負載情況。
用volatie關鍵字來聲明iscompleted靜态字段,volatie字段不會被編輯器和處理器優化,隻能被單個線程通路。