今天看到有人说未同步的(非线程安全)ArrayList.SyncRoot返回的是它自己.开始我也这么认为,而且我还认为同步的(线程安全)ArrayList.SyncRoot 也就是包装过的, 返回的是原始的实例. 我用下面的代码试了一下, 发现不管同步与否的ArrayList.SyncRoot都不是它自己, 而且根本不是一个ArrayList. 不过Array.SyncRoot是它自己,而且Array没有提供静态Synchronized方法.
我现在疑问的是ArrayList.SyncRoot 到底是什么? 为什么锁它就行.ArrayList list = new ArrayList();Console.WriteLine("list.IsSynchronized? {0}", list.IsSynchronized);
Console.WriteLine("list.SyncRoot == list? {0}", list.SyncRoot == list);
Console.WriteLine();ArrayList sync = ArrayList.Synchronized(list);
Console.WriteLine("sync.IsSynchronized? {0}", sync.IsSynchronized);
Console.WriteLine("sync.SyncRoot == sync? {0}", sync.SyncRoot == sync);
Console.WriteLine();Console.WriteLine("list == sync? {0}", list == sync);
Console.WriteLine("list.SyncRoot == sync.SyncRoot? {0}", list.SyncRoot == sync.SyncRoot);
Console.WriteLine();Console.WriteLine("list.SyncRoot.GetType() = {0}", list.SyncRoot.GetType());
Console.WriteLine("sync.SyncRoot.GetType() = {0}", sync.SyncRoot.GetType());
Console.WriteLine();Console.WriteLine("list.SyncRoot is ArrayList ? {0}", list.SyncRoot is ArrayList);
Console.WriteLine();int[] array = new int[8];Console.WriteLine("array.IsSynchronized? {0}", array.IsSynchronized);
Console.WriteLine("array.SyncRoot == array? {0}", array.SyncRoot == array);
Console.WriteLine("array.SyncRoot is int[] ? {0}", array.SyncRoot is int[]);
Console.WriteLine();Console.Read();

解决方案 »

  1.   

    附上面代码的结果:list.IsSynchronized? False
    list.SyncRoot == list? Falsesync.IsSynchronized? True
    sync.SyncRoot == sync? Falselist == sync? False
    list.SyncRoot == sync.SyncRoot? Truelist.SyncRoot.GetType() = System.Object
    sync.SyncRoot.GetType() = System.Objectlist.SyncRoot is ArrayList ? Falsearray.IsSynchronized? False
    array.SyncRoot == array? True
    array.SyncRoot is int[] ? True
      

  2.   

    to givenchy: 你的意思是?
      

  3.   

    MSDN的文档不是已经说得很清楚了吗?ArrayList 派生类可以使用 SyncRoot 属性来提供它们自己的 ArrayList 同步版本。同步代码必须在 ArrayList 的 SyncRoot 上执行操作,而不是直接在 ArrayList 上执行操作。这确保了从其他对象派生的集合的正确操作。特别是,它维护了与其他线程的正确同步,这些线程可能会同时修改 ArrayList 对象。通过集合枚举在本质上不是一个线程安全的过程。甚至在对集合进行同步处理时,其他线程仍可以修改该集合,这会导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合,或者捕捉由于其他线程进行的更改而引发的异常。
      

  4.   

    谢谢 misvcom, 不过请看准问题: ArrayList.SyncRoot 到底是什么? 为什么锁它就行.
      

  5.   

    这只是一个普通的object对象,实现时只要锁定它就行了,lock(ArrayList.SyncRoot){}
      

  6.   

    我晕哦
    SyncRoot仅仅是用来“锁”的,锁住了它,你对ArrayList进行操作就不用担心同步问题了。ArrayList al = new ArrayList();
    lock(al.SyncRoot)
    {
        al.Add(......);//这里的操作不会有同步问题。
    }
      

  7.   

    这些都知道, 开这个贴子其实是想讨论它的内部实现. 大家怎么都不理解我的用意呢. 因为思归大虾涉及.net非常之广, 所以才请思归出山. 其实这东东除了微软的工程师们知道, 大家估计只能靠推理了. 请大家看好用意再回复, 如果感兴趣, 可以up一下吗!
      

  8.   

    Array.SyncRoot是它本身, 锁它当然可以理解. 但对于ArrayList, 网上你搜一下, 很多文章里说它也是它本身, 实验证明实际上不是. 如果只是一个Object, "list.SyncRoot == sync.SyncRoot? True" 这里sync是list的同步包装, 而它们的SyncRoot是同一个对象.先不管是什么对象,至少可以达到代码上的风格统一. 如果是一般的Object, 那sync在进行Add,Remove操作时岂不是要检查这个Object有没有上锁? 为什么要这样做呢? 直接返回未同步包装的list不行吗?
    原因只有一个, 那就是锁这个Object不会耽误读取! 有没有人赞同? 谈谈大家的看法!!! 不要只讨论怎么用的, 那样看MSDN就可以了.
      

  9.   

    我的理解是ArrayList根本就没有实现SyncRoot……
      

  10.   

    public virtual object SyncRoot
    {
          get
          {
                if (this._syncRoot == null)
                {
                      Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
                }
                return this._syncRoot;
          }
    }
     Interlocked.CompareExchange 方法 (Object, Object, Object)
    比较两个对象是否相等,如果相等,则替换其中一个对象。
    结论,这个SyncRoot本来就是一个object,也不可能用于线程同步……
      

  11.   

    我猜想SyncRoot的主要作用是ArrayList在做一个IList的包装的时候,返回IList的SyncRoot。
      

  12.   

    "结论,这个SyncRoot本来就是一个object,也不可能用于线程同步……"
    那MSDN里说锁SyncRoot可以同步线程怎么解释呢?"我猜想SyncRoot的主要作用是ArrayList在做一个IList的包装的时候,返回IList的SyncRoot。"
    这里的IList只是个接口, 实际又是什么对象呢?
      

  13.   

    ArrayList是可以为一个实现了IList的对象做包装的,提供一些额外的功能……