背景:
阅读新闻

.Net线程问题解答

[日期:2008-01-07] 来源:博客园  作者: [字体: ]

锁定与同步

CLR怎样实现lock(obj)锁定? 

  从原理上讲,lock和Syncronized Attribute都是用Moniter.Enter实现的,比如如下代码

object lockobj=new object();
lock(obj){  
//do things 
}
 
  在编译时,会被编译为类似 

try{
  Moniter.Enter(obj){
   //do things
  }
}
catch{}
finally{
  Moniter.Exit(obj);
}


  而[MethodImpl(MethodImplOptions.Synchronized)]标记为同步的方法会在编译时被lock(this)语句所环绕
所以我们只简单探讨Moniter.Enter的实现

  (注:DotNet并非使用Win32API的CriticalSection来实现Moniter.Enter,不过他为托管对象提供了一个类似的结构叫做Syncblk)

  每个对象实例头部都有一个指针,这个指针指向的结构,包含了对象的锁定信息,当第一次使用Moniter.Enter(obj)时,这个obj对象的锁定结构就会被初时化,第二次调用Moniter.Enter时,会检验这个object的锁定结构,如果锁没有被释放,则调用会阻塞

 
  
WaitHandle是什么,他和他的派生类怎么使用 

  WaitHandle是Mutex,Semaphore,EventWaitHandler,AutoResetEvent,ManualResetEvent共同的祖先,他们包装了用于同步的内核对象,也就是说是这些内核对象的托管版本。

  Mutex:类似于一个接力棒,拿到接力棒的线程才可以开始跑,当然接力棒一次只属于一个线程(Thread Affinity),如果这个线程不释放接力棒(Mutex.ReleaseMutex),那么没办法,其他所有需要接力棒运行的线程都知道能等着看热闹

  Semaphore:类似于一个小桶,里面装了几个小球,凡是拿到小球就可以跑,比如指定小桶里最初有四个小球,那么开始的四个线程就可以直接拿着自己的小球开跑,但是第五个线程一看,小球被拿光了,就只好乖乖的等着有谁放一个小球到小桶里(Semophore.Release),他才能跑,但是这里的游戏规则比较特殊,我们可以随意向小桶里放入小球,也就是说我可以拿走一个小球,放回去俩,甚至一个都不拿,放回去5个,这样就有五个线程可以拿着这些小球运行了.我们可以规定小桶里有开始有几个小球(构造函数的第一个参数),也可以规定最多不能超过多少小球(构造函数的第二个参数) 

 ManualResetEvent,AutoResetEvent可以参考http://www.cnblogs.com/uubox/archive/2007/12/18/1003953.html 


什么是用双锁实现Singleton,为什么要这样做,双锁检验是不安全的吗? 

使用双锁检验技巧来实现单件,来自于Java社区

public static MySingleton Instance{
get{
    if(_instance!=null)}{
        lock(_instance){
            if(s_value==null){
                _instance= new MySingleton();
            }
        }
    }
}
}


这样做其实是为了提高效率,比起 

public static MySingleton Instance{
get{
lock(_instance){
if(s_value==null){
_instance= new MySingleton();
}
}

  前一种方法在instance创建的时候不需要用lock同步,从而增进了效率

  在java中这种技巧被证明是不安全的详细见http://www.cs.umd.edu/~pugh/java/memoryModel/

  但是在.Net下,这样的技巧是成立的,因为.Net使用了改进的内存模型

  并且在.Net下,我们可以使用LazyInit来实现单件

private static readonly _instance=new MySingleton()
public static MySingleton Instance{
get{return _instance}
}


  当第一此使用_instance时,CLR会生成这个对象,以后再访问这个字段,将会直接返回

互斥对象(Mutex),信号量(Semaphore),事件(Event)对象与lock语句的比较 

  首先这里所谓的事件对象不是System.Event,而是一种用于同步的内核机制

  互斥对象和事件对象属于内核对象,利用内核对象进行线程同步,线程必须要在用户模式和内核模式间切换,所以一般效率很低,但利用互斥对象和事件对象这样的内核对象,可以在多个进程中的各个线程间进行同步。

lock或者Moniter是.net用一个特殊结构实现的,不涉及模式切换,也就是说工作在用户方式下,同步速度较快,但是不能跨进程同步

收藏 推荐 打印 | 录入:木鸟 | 阅读:
相关新闻      
本文评论   [发表评论]   全部评论 (0)
热门评论