首页 > 代码库 > c#lock语句及在单例模式中应用

c#lock语句及在单例模式中应用

C#中的lock语句是怎么回事,有什么作用?

C#中的lock语句将lock中的语句块视为临界区,让多线程访问临界区代码时,必须顺序访问。他的作用是在多线程环境下,确保临界区中的对象只被一个线程操作,防止出现对象被多次改变情况。

注意的地方有:lock对象必须是一个不可变对象,否则无法阻止另一个线程进入临界区。最好是private static readonly 或者private static。常见的lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 都是不合理的写法。

原因:

1.lock(this),主要问题是如果类为实例化类,那么this也只是当前实例,不能起到锁定的作用,而且即使是静态类可以被锁定,那么由于尺寸问题,不如锁定不可变小对象合算。

2.lock(typeof())问题在于锁定对象类型当相于锁定类型中的静态对象部分,锁定了所有实例,速度慢;另一方面,有可能程序其他部分在访问该对象,已经替您锁定,将导致您锁定语句的挂起。原文(Here‘s why: Since there‘s one type object for all instances of a class, it would appear that locking it would provide a lock equivalent to locking a static object contained in your class. You would lock all instances of the class, wait until other threads were done accessing any part of any instance, then lock access so you could access static members safely and without another thread interfering.)

3.lock("")问题在于微软将内容相同的字符串视为同一个对象,如果您在此锁定了他,那么其实是锁定了同一个对象,将阻止其他地方对字符串的锁定。

 

lock语句的一个典型应用就是单例模式。 而单例模式的一个最简单实现方式就是用静态对象方式。如下:

public class ABicycle {      private static ABicycle aBicycle = new ABicycle();       public ABicycle Instance()      {            return aBicycle;      }} 

 

这是实现单例模式最简单的一种方式,但是有一个缺点就是假如ABicycle类被提前调用后,aBicycle即被实例化,没法做到实例化延迟。在此情况下,利用一个关联类可以避免此问题的发生。即:

public class ABicycle {     public ABicycle Instance()     {            return ABicycleStance.Instance();     } } private class ABicycleStance {      internal static readonly ABicycle aBicycle = new ABicycle();      public ABicycle Instance()      {            return aBicycle;      } }

 

单例模式的一个思路是利用C#的lock语句实现。 最简单实现方式为:

if(... == null){ ... = new ... } return ...; 

 

如果这样实现,有一个问题无法回避,即无法确保只能让一个线程使对象实例化,因为有可能多个线程并发执行到此,同时实例化了对象。为此,需要引用lock语句。引用的方式也有讲究,最直接的实现方式就是:

private static readonly locker = new object(); //或者这样写也可以。 //private static locker = new object(); lock(locker) {     if(.. == null)     {         ...     } } 

 

上面做法可行,但是有一个问题是每次返回时首先要对locker上锁,这样就牺牲了一些本来不必牺牲的性能,因此,可以修改为以下做法:

private static readonly locker = new object();if(.. == null)   {       lock(locker)       {             if(... == null)            {      }       } } 

 

这样,对于多线程来说是安全的,而且不必每次加锁,只有在判断对象没有实例化时加锁,避免了性能上的损失。

参考资料:

http://msdn.microsoft.com/zh-cn/library/c5kehkcz.aspx

http://hi.baidu.com/benzhan/item/6304481419d6360dd1d66dff

http://bytes.com/topic/c-sharp/answers/249277-dont-lock-type-objects