C#中Lock的用法

來源:互聯網
上載者:User

標籤:style   使用   strong   資料   io   art   

lock 關鍵字將語句塊標記為臨界區,方法是擷取給定對象的互斥鎖,執行語句,然後釋放該鎖。

 

lock語句根本使用的就是Monitor.Enter和Monitor.Exit,也就是說lock(this)時執行Monitor.Enter(this),大括弧結束時執行Monitor.Exit(this).他的意義在於什麼呢,對於任何一個對象來說,他在記憶體中的第一部分放置的是所有方法的地址,第二部分放著一個索引,他指向CLR中的SyncBlock Cache地區中的一個SyncBlock.什麼意思呢?就是說,當你執行Monitor.Enter(Object)時,如果object的索引值為負數,就從SyncBlock Cache中選區一個SyncBlock,將其地址放在object的索引中。這樣就完成了以object為標誌的鎖定,其他的線程想再次進行Monitor.Enter(object)操作,將獲得object為正數的索引,然後就等待。直到索引變為負數,即線程使用Monitor.Exit(object)將索引變為負數。

使用lock需要注意的地方:

1.lock不能鎖定空值某一對象可以指向Null,但Null是不需要被釋放的。(請參考:認識全面的null) 2.lock不能鎖定string類型,雖然它也是參考型別的。因為字串類型被CLR“暫留”

這意味著整個程式中任何給定字串都只有一個執行個體,就是這同一個對象表示了所有啟動並執行應用程式定義域的所有線程中的該文本。因此,只要在應用程式進程中的任何位置處具有相同內容的字串上放置了鎖,就將鎖定應用程式中該字串的所有執行個體。因此,最好鎖定不會被暫留的私人或受保護的成員。 3.lock鎖定的對象是一個程式塊的記憶體邊界 4.實值型別不能被lock,因為前文標紅字的“對象被釋放”,實值型別不是參考型別的

5.lock就避免鎖定public 類型或不受程式控制的對象。 例如,如果該執行個體可以被公開訪問,則 lock(this) 可能會有問題,因為不受控制的代碼也可能會鎖定該對象。這可能導致死結,即兩個或更多個線程等待釋放同一對象。出於同樣的原因,鎖定公用資料類型(相比於對象)也可能導致問題。 使用lock(this)的時候,類的成員變數的值可能會被不在臨界區的方法改值了

 

應用情境:經常會應用於防止多線程操作導致公用變數值出現不確定的異常,用於確保操作的安全性

樣本:

 

// statements_lock2.cs using System;

using System.Threading;

 

class Account {    

   private Object thisLock = new Object();    

   int balance;

 

    Random r = new Random();

 

    public Account(int initial)    

    {        

      balance = initial;    

    }

 

    int Withdraw(int amount)    

    {

 

        // This condition will never be true unless the lock statement        

      // is commented out:        

     if (balance < 0)        

       {            

        throw new Exception("Negative Balance");        

      }

 

        // Comment out the next line to see the effect of leaving out        

       // the lock keyword:        

       lock(thisLock)        

       {            

         if (balance >= amount)   

           {          

           Console.WriteLine("Balance before Withdrawal :  " + balance);

           Console.WriteLine("Amount to Withdraw        : -" + amount);

           balance = balance - amount;    

           Console.WriteLine("Balance after Withdrawal  :  " + balance);

            return amount;

            }            

        else  

           {  

            return 0;

          // transaction rejected

            }

         }

      }

 

    public void DoTransactions()

    {

        for (int i = 0; i < 100; i++)

        {

            Withdraw(r.Next(1, 100));

        }

     }

   }

 

class Test {

    static void Main()

    {

        Thread[] threads = new Thread[10];

        Account acc = new Account(1000);

        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].Start();

        }

     }

   }

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.