基本知識,無參數Thread和帶參數的Thread
Thread類的參數就是參數指針,可以傳入一個無參的函數。
如果要傳入帶參數的函數,先new一個ParameterizedThreadStart委托實例,帶參數的函數名作為它的參數。帶參數的函數必須且只能有一個object參數。參考下面的
ConterWithParam(object param)
static int iCnt = 0; static readonly int N = 10000; static void Main(string[] args) { Thread[] thrs = new Thread[N]; for (int i = 0; i < N; i++) { thrs[i] = new Thread(Counter); thrs[i].Start(); } for (int i = 0; i < N; i++) { thrs[i].Join(); } Console.WriteLine(iCnt); iCnt = 0; ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N]; object param = 2; for (int i = 0; i < N; i++) { thrsp[i] = new ParameterizedThreadStart(ConterWithParam); thrs[i] = new Thread(thrsp[i]); thrs[i].Start(param); } for (int i = 0; i < N; i++) { //當NewThread調用Join方法的時候,MainThread就被停止執行,直到NewThread線程執行完畢 thrs[i].Join(); } Console.WriteLine(iCnt); } static void Counter() { Thread.Sleep(100); iCnt++; //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt); } static void ConterWithParam(object param) { Thread.Sleep(100); int i = (int)param; iCnt += i; //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt); }
該例子輸出結果
2)互斥信號燈mutex
第一節的結果是不是有點奇怪。明明加了10000次,結果卻是9550.
帶參數的那個例子,一次加2,加10000次,應該是20000才對。結果卻是19678.
這是因為對全局變量的訪問iCnt出現了沖突。比如兩個線程同時取到了iCnt=0時的值,同時執行了i++,那么iCnt的最后狀態肯定是1,而不是會2。為了讓iCnt得到正確的值。
我們引入互斥信號燈。
static int iCnt = 0; static readonly int N = 10000; static Mutex mut = new Mutex(); static void Main(string[] args) { Thread[] thrs = new Thread[N]; for (int i = 0; i < N; i++) { thrs[i] = new Thread(Counter); thrs[i].Start(); } for (int i = 0; i < N; i++) { thrs[i].Join(); } Console.WriteLine(iCnt); iCnt = 0; ParameterizedThreadStart[] thrsp = new ParameterizedThreadStart[N]; object param = 2; for (int i = 0; i < N; i++) { thrsp[i] = new ParameterizedThreadStart(ConterWithParam); thrs[i] = new Thread(thrsp[i]); thrs[i].Start(param); } for (int i = 0; i < N; i++) { //當NewThread調用Join方法的時候,MainThread就被停止執行,直到NewThread線程執行完畢 thrs[i].Join(); } Console.WriteLine(iCnt); } static void Counter() { Thread.Sleep(10); //鎖 mut.WaitOne(); iCnt++; //釋放 mut.ReleaseMutex(); //Console.WriteLine("finish iCnt++,now iCnt is " + iCnt); } static void ConterWithParam(object param) { Thread.Sleep(10); //鎖住 mut.WaitOne(); int i = (int)param; iCnt += i; //釋放 mut.ReleaseMutex(); //Console.WriteLine("finish iCnt+"+i+",now iCnt is " + iCnt); }
本次執行結果
3) 同步信號燈Semaphore
用最經典的生產者-消費者來解釋。
static Semaphore sem = new Semaphore(0, 1); static Semaphore sem2 = new Semaphore(0, 5); static void Main(string[] args) { Console.WriteLine("消費者等生產者生產一個item"); Thread thConsumer = new Thread(Consume); thConsumer.Start(); Thread thProductor = new Thread(Product); thProductor.Start(); thConsumer.Join(); thProductor.Join(); Console.WriteLine("............................."); Console.WriteLine("多並發的例子....."); for (int i = 0; i < 10; i++) { Thread t1 = new Thread(Consume2); t1.Start(); Thread t2 = new Thread(Product2); t2.Start(); }//end for } static void Product() { Thread.Sleep(2000); Console.WriteLine("Product an item..."); sem.Release(); } static void Consume() { Thread.Sleep(1000); Console.WriteLine("Consumer is waiting an item..."); sem.WaitOne(); Console.WriteLine("Consumer get an item..."); } static void Product2() { Thread.Sleep(1000); Console.WriteLine("Product an item..."); sem2.Release(); } static void Consume2() { Thread.Sleep(1000); Console.WriteLine("Consumer is waiting an item..."); sem2.WaitOne(); Console.WriteLine("Consumer get an item..."); }