Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6276638
  • 博文数量: 2759
  • 博客积分: 1021
  • 博客等级: 中士
  • 技术积分: 4091
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-11 14:14
文章分类

全部博文(2759)

文章存档

2019年(1)

2017年(84)

2016年(196)

2015年(204)

2014年(636)

2013年(1176)

2012年(463)

分类: C#/.net

2013-04-02 08:43:13

原文地址:多线程处理之lock语句 作者:dyli2000

    lock 关键字将语句块标记为临界区,方法是获取给定对象的互斥锁,执行语句,然后释放该锁。

案例1、


  1. class ThreadingExample
  2. {
  3.     class C1
  4.     {
  5.         private bool deadlocked = true;
  6.         private object locker = new object();
  7.         public void LockMe(object o)
  8.         {
  9.             //lock (this)
  10.             lock(locker)
  11.             {
  12.                 while (deadlocked)
  13.                 {
  14.                     deadlocked = (bool)o;
  15.                     Console.WriteLine("I am locked:(");
  16.                     Thread.Sleep(500);
  17.                 }
  18.             }
  19.         }
  20.         public void DoNotLockMe()
  21.         {
  22.             Console.WriteLine("I am not locked:");
  23.         }
  24.     };
  25.     static void Main()
  26.     {
  27.         C1 c1 = new C1();
  28.         Thread t1 = new Thread(c1.LockMe);
  29.         t1.Start(true);
  30.         Thread.Sleep(100);
  31.         //lock (c1)
  32.         //{
  33.             c1.DoNotLockMe();
  34.             c1.LockMe(false);
  35.        // }
  36.         Console.ReadLine();
  37.     }
  38. }


 

image

关键点:

1. lock(this)的缺点就是在一个线程(例如本例的t1)通过执行该类的某个使用"lock(this)"的方法(例如本例的LockMe())锁定某对象之后, 导致整个对象无法被其他线程(例如本例的主线程)访问 - 因为程序员可以在任何其他线程(例如本例的主线程)访问该类的时候使用类似lock(c1)的代码,因此我们在设计类的时候就最好未雨绸缪,而不是把负担留给用户。

2. 我们应该使用不影响其他操作和不会被外部对象锁定的的私有成员作为locker。

3. 在使用lock的时候,被lock的对象(locker)一定要是引用类型的,如果是值类型,将导致每次lock的时候都会将该对象装箱为一个新的引用对象(事实上如果使用值类型,C#编译器(3.5.30729.1)在编译时就会给出一个错误)。

 

MSDN上的案例


  1. namespace ThreadLock
  2. {
  3.     class Account
  4.     {
  5.         private Object thisLock = new Object();
  6.         int balance;
  7.         Random r = new Random();
  8.         public Account(int initial)
  9.         {
  10.             balance = initial;
  11.         }
  12.         int Withdraw(int amount)
  13.         {
  14.             // This condition will never be true unless the lock statement
  15.             // is commented out:
  16.             if (balance < 0)
  17.             {
  18.                 throw new Exception("Negative Balance");
  19.             }
  20.             // Comment out the next line to see the effect of leaving out
  21.             // the lock keyword:
  22.             lock (thisLock)
  23.             {
  24.                 if (balance >= amount)
  25.                 {
  26.                     Console.WriteLine("Balance before Withdrawal : " + balance);
  27.                     Console.WriteLine("Amount to Withdraw : -" + amount);
  28.                     balance = balance - amount;
  29.                     Console.WriteLine("Balance after Withdrawal : " + balance);
  30.                     return amount;
  31.                 }
  32.                 else
  33.                 {
  34.                     return 0; // transaction rejected
  35.                 }
  36.             }
  37.         }
  38.         public void DoTransactions()
  39.         {
  40.             for (int i = 0; i < 100; i++)
  41.             {
  42.                 Withdraw(r.Next(1, 100));
  43.             }
  44.         }
  45.     }
  46.     class Test
  47.     {
  48.         static void Main()
  49.         {
  50.             Thread[] threads = new Thread[10];
  51.             Account acc = new Account(1000);
  52.             for (int i = 0; i < 10; i++)
  53.             {
  54.                 Thread t = new Thread(new ThreadStart(acc.DoTransactions));
  55.                 threads[i] = t;
  56.             }
  57.             for (int i = 0; i < 10; i++)
  58.             {
  59.                 threads[i].Start();
  60.             }
  61.             Console.ReadLine();
  62.         }
  63.     }
  64. }


image

多个线程共同访问Account acc对象,使用lock(object)很好的处理这访问冲突的问题。

阅读(645) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~