lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。
案例1、
- class ThreadingExample
- {
- class C1
- {
- private bool deadlocked = true;
- private object locker = new object();
- public void LockMe(object o)
- {
- //lock (this)
- lock(locker)
- {
- while (deadlocked)
- {
- deadlocked = (bool)o;
- Console.WriteLine("I am locked:(");
- Thread.Sleep(500);
- }
- }
- }
- public void DoNotLockMe()
- {
- Console.WriteLine("I am not locked:");
- }
- };
- static void Main()
- {
- C1 c1 = new C1();
- Thread t1 = new Thread(c1.LockMe);
- t1.Start(true);
- Thread.Sleep(100);
- //lock (c1)
- //{
- c1.DoNotLockMe();
- c1.LockMe(false);
- // }
- Console.ReadLine();
- }
- }
关键点:
1. lock(this)的缺点就是在一个线程(例如本例的t1)通过执行该类的某个使用"lock(this)"的方法(例如本例的LockMe())锁定某对象之后, 导致整个对象无法被其他线程(例如本例的主线程)访问 - 因为程序员可以在任何其他线程(例如本例的主线程)访问该类的时候使用类似lock(c1)的代码,因此我们在设计类的时候就最好未雨绸缪,而不是把负担留给用户。
2. 我们应该使用不影响其他操作和不会被外部对象锁定的的私有成员作为locker。
3. 在使用lock的时候,被lock的对象(locker)一定要是引用类型的,如果是值类型,将导致每次lock的时候都会将该对象装箱为一个新的引用对象(事实上如果使用值类型,C#编译器(3.5.30729.1)在编译时就会给出一个错误)。
MSDN上的案例
- namespace ThreadLock
- {
- 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();
- }
- Console.ReadLine();
- }
- }
- }
多个线程共同访问Account acc对象,使用lock(object)很好的处理这访问冲突的问题。