c#多線程中Lock()關鍵字的使用

來源:互聯網
上載者:User

本文介紹C# lock關鍵字,C#提供了一個關鍵字lock,它可以把一段代碼定義為互斥段(critical section),互斥段在一個時刻內只允許一個線程進入執行,而其他線程必須等待。

每個線程都有自己的資源,但是代碼區是共用的,即每個線程都可以執行相同的函數。這可能帶來的問題就是幾個線程同時執行一個函數,導致資料的混亂,產生不可預料的結果,因此我們必須避免這種情況的發生。

其中,lock是一種比較好用的簡單的線程同步方式,它是通過為給定對象擷取互斥鎖來實現同步的。它可以保證當一個線程在關鍵程式碼片段的時候,另一個線程不會進來,它只能等待,等到那個線程對象被釋放,也就是說線程出了臨界區。用法:

 

public void Function(){    object lockThis = new object ();    lock (lockThis)    {        // Access thread-sensitive resources.    }}

下面是一個比較典型的使用C#  lock關鍵字的例子,其中在注釋裡說明了C# lock關鍵字的用法和用途。

Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->using System; using System.Threading; namespace ThreadSimple{     internal class Account    {         int balance; //餘額        Random r=new Random();         internal Account(int initial)          {              balance=initial;         }        internal int Withdraw(int amount) //取回、取款        {             if(balance<0)             {                  //如果balance小於0則拋出異常                  throw new Exception("NegativeBalance");//負的 餘額             }             //下面的代碼保證在當前線程修改balance的值完成之前             //不會有其他線程也執行這段代碼來修改balance的值              //因此,balance的值是不可能小於0的              lock(this)              {                 Console.WriteLine("CurrentThread:"+Thread.CurrentThread.Name);                 //如果沒有lock關鍵字的保護,那麼可能在執行完if的條件判斷(成立)之後                  //另外一個線程卻執行了balance=balance-amount修改了balance的值                 //而這個修改對這個線程是不可見的,所以可能導致這時if的條件已經不成立了                 //但是,這個線程卻繼續執行 balance=balance-amount,所以導致balance可能小於0                 if(balance>=amount)                 {                     Thread.Sleep(5);                    balance=balance-amount;                     return  amount;                 }  else                 {                     return 0;                    //transactionrejected                 }             }          }        internal void DoTransactions()//取款事務        {            for (int i = 0; i < 100; i++)            {                Withdraw(r.Next(-50, 100));            }        }    }       internal class Test      {          static internal Thread[] threads=new Thread[10];         public static void Main()          {              Account acc=new Account(0);             for(int i=0;i<10;i++)             {                  Thread t=new Thread(new ThreadStart(acc.DoTransactions));                threads[i]=t;             }            for (int i = 0; i < 10; i++)            {                threads[i].Name = i.ToString();            }            for (int i = 0; i < 10; i++)            {                threads[i].Start();                Console.ReadLine();            }        }    } }

lock的參數必須是基於參考型別的對象,不要是基本類型像bool,int什麼的,這樣根本不能同步,原因是lock的參數要求是對象,如果傳入int,勢必要發生裝箱操作,這樣每次lock的都將是一個新的不同的對象。最好避免使用public類型或不受程式控制的對象執行個體,因為這樣很可能導致死結。特別是不要使用字串作為lock的參數,因為字串被CLR“暫留”,就是說整個應用程式中給定的字串都只有一個執行個體,因此更容易造成死結現象。建議使用不被“暫留”的私人或受保護的成員作為參數。其實某些類已經提供了專門用於被鎖的成員,比如Array類型提供SyncRoot,許多其它集合類型也都提供了SyncRoot。

所以,使用lock應該注意以下幾點:
1、如果一個類的執行個體是public的,最好不要lock(this)。因為使用你的類的人也許不知道你用了lock,如果他new了一個執行個體,並且對這個執行個體上鎖,就很容易造成死結。
2、如果MyType是public的,不要lock(typeof(MyType))。
3、永遠也不要lock一個字串。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.