zoukankan      html  css  js  c++  java
  • lock关键字 应用之研究

    msdn关于lock有段话:通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:如果实例可以被公共访问,将出现 lock (this) 问题。如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。来看看lock(this)的问题:如果有一个类Class1,该类有一个方法用lock(this)来实现互斥:
    public void Method2()
            {
                lock (this)
                {
                    System.Windows.Forms.MessageBox.Show("Method2 End");
                }
            }
        如果在同一个Class1的实例中,该Method2能够互斥的执行。但是如果是2个Class1的实例分别来执行Method2,是没有互斥效果的。因为这里的lock,只是对当前的实例对象进行了加锁。
        Lock(typeof(MyType))锁定住的对象范围更为广泛,由于一个类的所有实例都只有一个类型对象(该对象是typeof的返回结果),锁定它,就锁定了该对象的所有实例,微软现在建议(原文请参考:http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/SDaskgui06032003.mspx?mfr=true)不要使用lock(typeof(MyType)),因为锁定类型对象是个很缓慢的过程,并且类中的其他线程、甚至在同一个应用程序域中运行的其他程序都可以访问该类型对象,因此,它们就有可能代替您锁定类型对象,完全阻止您的执行,从而导致你自己的代码的挂起。
        锁住一个字符串更为神奇,只要字符串内容相同,就能引起程序挂起。原因是在.NET中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.NET会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(“my lock”)的话,它们实际锁住的是同一个对象。到此,微软给出了个lock的建议用法:锁定一个私有的static 成员变量。
          .NET在一些集合类中(比如ArrayList,HashTable,Queue,Stack)已经提供了一个供lock使用的对象SyncRoot,用Reflector工具查看了SyncRoot属性的代码,在Array中,该属性只有一句话:return this,这样和lock array的当前实例是一样的。ArrayList中的SyncRoot有所不同  get
        {
            if (this._syncRoot == null)
            {
                Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
            }
            return this._syncRoot;
       其中Interlocked类是专门为多个线程共享的变量提供原子操作(如果你想锁定的对象是基本数据类型,那么请使用这个类),CompareExchange方法将当前syncRoot和null做比较,如果相等,就替换成new object(),这样做是为了保证多个线程在使用syncRoot时是线程安全的。集合类中还有一个方法是和同步相关的:Synchronized,该方法返回一个对应的集合类的wrapper类,该类是线程安全的,因为他的大部分方法都用lock来进行了同步处理,比如Add方法: public override void Add(object key, object value)
    {
        lock (this._table.SyncRoot)
        {
            this._table.Add(key, value);
        }
    }
        这里要特别注意的是MSDN提到:从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合: Queue myCollection = new Queue();
      lock(myCollection.SyncRoot) {
      foreach (Object item in myCollection) {
      // Insert your code here.
      }
     }

    另外lock实质是对监视器(Monitor)的封装。相对于监视器(Monitor),使用更方便,优雅。
    本篇文章来源于:http://www.boy5d.com/article/html/2007-12/697.html

  • 相关阅读:
    OD 实验(十六)
    OD 实验(十五)
    OD 实验(十四)
    建立和安装requirements.txt依赖
    不吟诗的会计不是好程序员
    python并发编程--进程&线程--其他模块-从菜鸟到老鸟(三)
    python并发编程--协程---从菜鸟到老鸟(四)
    如何加速pandas的DataFrame
    python web
    mysql 数据类型隐式转化
  • 原文地址:https://www.cnblogs.com/sutengcn/p/1047576.html
Copyright © 2011-2022 走看看