来自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=392
GPS平台、网站建设、软件开发、系统运维,找森大网络科技!
http://cnsendnet.taobao.comphp
一. 为何要lock,lock了什么?安全
当咱们使用线程的时候,效率最高的方式固然是异步,即各个线程同时运行,其间不相互依赖和等待。但当不一样的线程都须要访问某个资源的时候,就须要同步机制了,也就是说当对同一个资源进行读写的时候,咱们要使该资源在同一时刻只能被一个线程操做,以确保每一个操做都是有效即时的,也即保证其操做的原子性。lock是C#中最经常使用的同步方式,格式为lock(objectA){codeB} 。网络
lock(objectA){codeB} 看似简单,实际上有三个意思,这对于适当地使用它相当重要:运维
二. lock(this)怎么了?异步
咱们看一个例子:ide
using System; using System.Threading; namespace Namespace1 { class C1 { private bool deadlocked= true; //这个方法用到了lock,咱们但愿lock的代码在同一时刻只能由一个线程访问 public void LockMe(object o) { lock (this) { while(deadlocked) { deadlocked = (bool)o; Console.WriteLine("Foo: I am locked :("); Thread.Sleep(500); } } } //全部线程均可以同时访问的方法 public void DoNotLockMe() { Console.WriteLine("I am not locked :)"); } } class Program { staticvoid Main(string[] args) { C1 c1 =new C1(); //在t1线程中调用LockMe,并将deadlock设为true(将出现死锁) Thread t1= new Thread(c1.LockMe); t1.Start(true); Thread.Sleep(100); //在主线程中lock c1 lock (c1) { //调用没有被lock的方法 c1.DoNotLockMe(); //调用被lock的方法,并试图将deadlock解除 c1.LockMe(false); } } }
在t1线程中,LockMe调用了lock(this), 也就是Main函数中的c1,这时候在主线程中调用lock(c1)时,必需要等待t1中的lock块执行完毕以后才能访问c1,即全部c1相关的操做都没法完成,因而咱们看到连c1.DoNotLockMe()都没有执行。函数
把C1的代码稍做改动:网站
class C1 { privatebool deadlocked= true; private object locker= new object(); //这个方法用到了lock,咱们但愿lock的代码在同一时刻只能由一个线程访问 public void LockMe(object o) { lock (locker) { while(deadlocked) { deadlocked = (bool)o; Console.WriteLine("Foo: I am locked :("); Thread.Sleep(500); } } } //全部线程均可以同时访问的方法 public void DoNotLockMe() { Console.WriteLine("I am not locked :)"); } }
此次咱们使用一个私有成员做为锁定变量(locker),在LockMe中仅仅锁定这个私有locker,而不是整个对象。这时候从新运行程序,能够看到虽然t1出现了死锁,DoNotLockMe()仍然能够由主线程访问;LockMe()依然不能访问,缘由是其中锁定的locker尚未被t1释放。this
关键点:spa
kenny add
而对于Monitor,发现它的静态方法Enter(object obj)有一个异常类型ArgumentNullException,
执行lock(null对象 )处,抛出未处理的异常:System.ArgumentNullException: 值不能为空!
在代码段中修改锁定对象,会出现 blance<0的状况,并会抛出异常
private static readonly object obj = new object();
为何要设置成只读的呢?这是由于若是在lock代码段中改变obj的值,其它线程就畅通无阻了,由于互斥锁的对象变了,object.ReferenceEquals必然返回false。
因此把上面的修改为private static readonly
来自森大科技官方博客
http://www.cnsendblog.com/index.php/?p=392
GPS平台、网站建设、软件开发、系统运维,找森大网络科技!
http://cnsendnet.taobao.com