内容参考自:http://daimajishu.iteye.com/blog/1079107
四.lock应避免锁定public 类型或不受程序控制的对象,举例
lock就是把一段代码定义为临界区,所谓临界区就是同一时刻只能有一个线程来操作临界区的代码,当一个线程位于代码的临界区时,另一个线程不能进入临界区,如果试图进入临界区,则只能一直等待(即被阻止),直到已经进入临界区的线程访问完毕,并释放锁旗标。
其基本使用方式如下:
class Test { //定义一个私有成员变量,用于Lock的锁定标志 private static object lockobj = new object(); void DoSomething() { lock (lockobj) { //需要锁定的代码块 } } }
最经典的例子,莫过于模拟银行5个窗口取钱操作的例子了,5个窗口是5个线程,都要取钱,但是同一刻只能有一个窗口可以进行真正的取钱操作(钱数的数值计算,剩余多少等这些代码必须定义为临界区),其他只有等待,其代码如下:
class Account { 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 (this) { if (balance >= amount) { Console.WriteLine("提款窗口: " + Thread.CurrentThread.Name); Console.WriteLine("提款之前余额(Balance before Withdrawal): " + balance); Console.WriteLine("提款数量(Amount to Withdraw) : -" + amount); balance = balance - amount; Console.WriteLine("提款之后余额(Balance after Withdrawal) : " + balance); Console.WriteLine(); return amount; } else return 0; // transaction rejected } } public void DoTransactions() { //模拟100个人来提款,每次提1-30元 for (int i = 0; i < 100; i++) Withdraw(r.Next(1, 30)); } } class Test { public static void MainXXX() { Thread[] threads = new Thread[5]; //总额为100元 Account acc = new Account(100); //定义并初始化5个线程,模拟银行的5个窗口 for (int i = 0; i < 5; i++) { Thread t = new Thread(new ThreadStart(acc.DoTransactions)) { Name = i + "号" }; threads[i] = t; } //启动5个线程,模拟银行的5个窗口开始工作 for (int i = 0; i < 5; i++) { Console.WriteLine("threads[{0}].Start()", i); threads[i].Start(); } } }