首頁  >  文章  >  後端開發  >  C#的多線程機制初探(4)

C#的多線程機制初探(4)

黄舟
黄舟原創
2016-12-21 15:02:031099瀏覽

exPRession代表你希望追蹤的對象,通常是對象引用。一般地,如果你想保護一個類別的實例,你可以使用this;如果你希望保護一個靜態變數(如互斥程式碼段在一個靜態方法內部),一般使用類別名稱就可以了。而statement_block就是互斥段的程式碼,這段程式碼在一個時刻內只可能被一個執行緒執行。

  以下是一個使用lock關鍵字的典型例子,我將在註釋裡向大家說明lock關鍵字的用法和用途:

//lock.cs 
using System; 
using. Threading;

internal class Account 
{ 
int balance; 
Random r = interdom);
 { 
balance = initial; 
}

internal int Withdraw(int amountmount if (balance { 
//如果balance小於0則拋出異常 
 } 
//下面的程式碼保證在當前線程修改balance的值完成之前 
//不會有其他線程也執行這段程式碼
//因此,balance的值是不可能小於0的 
lock (this) 
{ 
Console. WriteLine("Current Thread:"+Thread.CurrentThread.Name); 
//如果沒有lock關鍵字的保護,那麼可能在執行完單的條件判斷//另外一個線程卻執行了balance=balance-amount修改了balance的值 
///而這個修改對這個線程是不可見的,所以可能導致這時if的條件已經不成立了 
//但是,這個線程卻繼續執行balance=balance-amount,所以導致balance可能小於0 
=mount (
{ 
Thread.Sleep(5); 
 return amount; 
} 

 return 0; // transaction rejected 
} 
} { 
 for (int i = 0; i Withdraw(r.Next(-50, 100));
internal class Test 
{ 
static internal Thread[] threads = new Thread[10]; 
  Account acc = new Account (0); 
for (int i = 0; i  = new Thread(new ThreadStart(acc.DoTransactions)); 
threads[i] = t; 
  ; i threads[i].Name=i.ToString(); 
for (int i10; i threads[i].Start(); 
Console.ReadLine(); 
}也會出現和公用程式碼類似的問題,這種問題就不應該使用lock關鍵字了,這裡需要用到System.Threading中的一個類別Monitor,我們可以稱之為監視器,Monitor提供了讓線程共享資源的方案。

  Monitor類別可以鎖定一個對象,一個執行緒只有得到這把鎖才可以對該對象進行操作。物件鎖機制保證了在可能造成混亂的情況下一個時刻只有一個執行緒可以存取這個物件。 Monitor必須和一個具體的對象相關聯,但是由於它是一個靜態的類,所以不能使用它來定義對象,而且它的所有方法都是靜態的,不能使用對象來引用。以下程式碼說明了使用Monitor鎖定一個物件的情形:

...... 
Queue oQueue=new Queue(); 
...... 
Monitor.Enter(oQueueEnt ); 
......//現在oQueue物件只能被目前執行緒操縱了 
Monitor.Exit(oQueue);//釋放鎖

如上所示,當一個執行緒呼叫Monitor.Enter()方法鎖定一個物件時,這個物件就歸它所有了,其它執行緒想要存取這個對象,只有等待它使用Monitor.Exit()方法釋放鎖。為了確保執行緒最終都能釋放鎖,你可以把Monitor.Exit()方法寫在try-catch-finally結構中的finally程式碼區塊裡。對於任何一個被Monitor鎖定的對象,內存中都保存著與它相關的一些信息,其一是現在持有鎖的線程的引用,其二是一個預備隊列,隊列中保存了已經準備好獲取鎖的線程,其三是一個等待隊列,隊列中保存著當前正在等待這個物件狀態改變的隊列的引用。當擁有物件鎖的線程準備釋放鎖時,它使用Monitor.Pulse()方法通知等待佇列中的第一個線程,於是該線程被轉移到預備佇列中,當物件鎖被釋放時,在預備佇列中的執行緒可以立即獲得物件鎖。

下面是一個展示如何使用lock關鍵字和Monitor類別來實現線程的同步和通訊的例子,也是一個典型的生產者與消費者問題。在這個例程中,生產者線程和消費者線程是交替進行的,生產者寫入一個數,消費者立即讀取並且顯示,我將在註釋中介紹該程式的精要所在。使用到的系統命名空間如下:

using System; 
using System.Threading

 以上就是C#的多線程機制初探(4)的內容,更多相關內容請關注中文PHPwww. php.cn)! 


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn