lock 陳述式 (C# 參考)

更新:2007 年 11 月

lock 關鍵字可將陳述式區塊標記為關鍵區段 (Critical Section),其做法是為指定的物件取得互斥鎖定、執行陳述式,接著釋出該鎖定。陳述式採用下列形式:

Object thisLock = new Object();
lock (thisLock)
{
    // Critical code section.
}

如需詳細資訊,請參閱執行緒同步處理 (C# 程式設計手冊)

備註

lock 關鍵字可保證有執行緒在關鍵區段時,絕對不會有任何其他執行緒同時也進入這個關鍵區段執行。如果其他執行緒嘗試進入已鎖定的程式碼,它將會等候、封鎖,直到該物件被釋出。

執行緒 (C# 程式設計手冊) 這一章節會討論執行緒的處理。

lock 關鍵字會在區塊開始執行時呼叫 Enter,並在區塊結束時呼叫 Exit

一般而言,請避免鎖定 public 型別或程式碼無法控制的執行個體。有三種常見的建構,分別為 lock (this)、lock (typeof (MyType)) 和 lock ("myLock"),違反這項方針:

  • lock (this) 在可公開存取執行個體的情況下,會是問題所在。

  • lock (typeof (MyType)) 在可公開存取 MyType 的情況下,會是問題所在。

  • lock(“myLock”) 會是問題所在,因為使用相同字串的處理序中若有任何其他程式碼,將會共用相同的鎖定。

最佳作法是定義要鎖定的 private 物件,或者定義 private static 物件變數保護所有執行個體通用的資料。

範例

以下的範例顯示在 C# 中執行緒 (但不用鎖定) 的簡易用法。

//using System.Threading;

class ThreadTest
{
    public void RunMe()
    {
        Console.WriteLine("RunMe called");
    }

    static void Main()
    {
        ThreadTest b = new ThreadTest();
        Thread t = new Thread(b.RunMe);
        t.Start();
    }
}
// Output: RunMe called

下列範例使用到執行緒與 lock。只要 lock 陳述式存在,此陳述式區塊就是關鍵區段,而且 balance 永遠不會成為負數。

// 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();
        }
    }
}

C# 語言規格

如需詳細資料,請參閱 C# 語言規格中的下列章節:

  • 5.3.3.18 Lock 陳述式

  • 8.12 lock 陳述式

請參閱

工作

監視同步處理技術範例

等候同步處理技術範例

概念

C# 程式設計手冊

監視器

Interlocked 作業

AutoResetEvent

參考

執行緒 (C# 程式設計手冊)

C# 關鍵字

陳述式關鍵字 (C# 參考)

MethodImplAttributes

Mutex

執行緒同步處理 (C# 程式設計手冊)

其他資源

C# 參考