Lock Statement in C#
The lock keyword marks a statement block as a critical section by obtaining the mutual-exclusion lock for a given object, executing a statement, and then releasing the lock. This statement takes the following form
Object thisLock = new Object(); lock (thisLock) { // Critical code section. }
For more information, see Thread Synchronization (C# Programming Guide).(MSDN link)
The lock keyword ensures that one thread does not enter a critical section of
code while another thread is in the critical section. If another thread tries
to enter a locked code, it will wait, block, until the object is released.
The section Threading (C# Programming Guide)(MSDN LINK) discusses threading.
The lock keyword calls Enter at the start of the block and Exit at the end of the block.
In general, avoid locking on a public type, or instances beyond your code's control. The common constructs
lock (this), lock (typeof (MyType)), andlock ("myLock") violate this guideline:
- lock (this) is a problem if the instance can be accessed publicly.
- lock (typeof (MyType)) is a problem if MyType is publicly accessible.
- lock("myLock") is a problem because any other code in the process using the same string, will share the same lock.
Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.)
The following sample shows a simple use of threads without locking in 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
The following sample uses threads and lock. As long as the lock statement is present, the statement block is a critical section and balance will never become a negative number.// 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(); } } }
Comments
Post a Comment