多綫程按順序輸出數字(信号量的使用)
一道經典的面試題:
使用兩個綫程按順序輸出1-100的數字,一個綫程輸出奇數,一個綫程輸出偶數。
看似很簡單,可是在綫程中用lock很輕鬆的實現鎖定綫程判斷變量奇偶性來控制打印和輸出,如果僅僅是這樣那麽就這道題就失去了考察的意義。
這道題實際上是在考察對綫程的控制,控制綫程同步的。
在C#中可以通過信號量這個東西來輕鬆控制綫程之間的同步,爲了更好的演示綫程的同步控制,示例中使用了三個綫程來演示。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Test { class Program { static void Main() { Console.WriteLine("Test"); Test(); } static void Test() { AutoResetEvent ateA = new AutoResetEvent(false); AutoResetEvent ateB = new AutoResetEvent(false); AutoResetEvent ateC = new AutoResetEvent(false); int i = 0; Thread th1 = new Thread((object ls) => { while (i < 100) { ateA.WaitOne(); if (i < 100) { Interlocked.Increment(ref i); Console.WriteLine(i + "线程id" + Thread.CurrentThread.ManagedThreadId); } ateB.Set(); } ateA.Close(); Console.WriteLine("线程A关闭"); }); th1.Start(); Thread th2 = new Thread((object ls) => { while (i < 100) { ateB.WaitOne(); if (i < 100) { Interlocked.Increment(ref i); Console.WriteLine(i + "线程id" + Thread.CurrentThread.ManagedThreadId); } ateC.Set(); } ateB.Close(); Console.WriteLine("线程B关闭"); }); th2.Start(); Thread th3 = new Thread((object ls) => { while (i < 100) { ateC.WaitOne(); if (i < 100) { Interlocked.Increment(ref i); Console.WriteLine(i + "线程id" + Thread.CurrentThread.ManagedThreadId); ateA.Set(); } } ateC.Set(); Console.WriteLine("线程C关闭"); }); th3.Start(); ateA.Set(); } } }
最終打印結果如下圖所示:

示例中使用的關鍵技術:
AutoResetEvent :通知正在等待的线程已发生事件
引申技術點:
ManualResetEvent :通知一个或多个正在等待的线程已发生事件
Semaphore :https://www.cnblogs.com/yifengjianbai/p/5468449.html 可以參考該文檔的説明進行學習

浙公网安备 33010602011771号