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语句的一个典型应用就是单例模式。 而单例模式的一个最简单实现方式就是用静态对象方式。如下:

1
2
3
4
5
6
7
public  class  ABicycle {  
    private  static  ABicycle aBicycle =  new  ABicycle();  
     public  ABicycle Instance()  
    {     
       return  aBicycle;  
    }
}

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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语句实现。 最简单实现方式为:

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

 

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

1
2
3
4
5
6
7
8
9
10
11
12
13
private  static  readonly  locker =  new  object ();
 
//或者这样写也可以。
 
//private static locker = new object();
 
lock (locker)
{  
   if (.. ==  null )  
   {   
      ...  
   }
}

 

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

1
2
3
4
5
6
7
8
9
10
11
12
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

文章出处:www.cnblogs.com/jizhong

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。否则保留追究法律责任的权利。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值