Csharp/C#教程:深入线程安全容器的实现方法分享

最近写了个小程序用到了C#4.0中的线程安全集合。想起很久以前用C#2.0开发的时候写后台windows服务,为了利用多线程实现生产者和消费者模型,经常要封装一些线程安全的容器,比如泛型队列和字典等等。下面就结合部分MS的源码和自己的开发经验浅显地分析一下如何实现线程安全容器以及实现线程安全容器容易产生的问题。

一、ArrayList

在C#早期版本中已经实现了线程安全的ArrayList,可以通过下面的方式构造线程安全的数组列表:

vararray=ArrayList.Synchronized(newArrayList());

我们从Synchronized方法入手,分析它的源代码看是如何实现线程安全的:
代码如下:

Synchronized       ///<summary>Returnsan<seecref=”T:System.Collections.ArrayList”/>wrapperthatissynchronized(threadsafe).</summary>
       ///<returns>An<seecref=”T:System.Collections.ArrayList”/>wrapperthatissynchronized(threadsafe).</returns>
       ///<paramname=”list”>The<seecref=”T:System.Collections.ArrayList”/>tosynchronize.</param>
       ///<exceptioncref=”T:System.ArgumentNullException”>
       ///  <paramrefname=”list”/>isnull.</exception>
       ///<filterpriority>2</filterpriority>
       [HostProtection(SecurityAction.LinkDemand,Synchronization=true)]
       publicstaticArrayListSynchronized(ArrayListlist)
       {
           if(list==null)
           {
               thrownewArgumentNullException(“list”);
           }
           returnnewArrayList.SyncArrayList(list);
       }

继续跟进去,发现SyncArrayList是一个继承自ArrayList的私有类,内部线程安全方法的实现经过分析,很多都是像下面这样lock(注意是lock_root对象而不是数组列表实例对象)一下完事:

lock(this._root)

有心的你可以查看SyncArrayList的源码:
代码如下:

SyncArrayList       [Serializable]
       privateclassSyncArrayList:ArrayList
       {
           privateArrayList_list;
           privateobject_root;
           publicoverrideintCapacity
           {
               get
               {
                   intcapacity;
                   lock(this._root)
                   {
                       capacity=this._list.Capacity;
                   }
                   returncapacity;
               }
               set
               {
                   lock(this._root)
                   {
                       this._list.Capacity=value;
                   }
               }
           }
           publicoverrideintCount
           {
               get
               {
                   intcount;
                   lock(this._root)
                   {
                       count=this._list.Count;
                   }
                   returncount;
               }
           }
           publicoverrideboolIsReadOnly
           {
           &nbs p;   get
               {
                   returnthis._list.IsReadOnly;
               }
           }
           publicoverrideboolIsFixedSize
           {
               get
               {
                   returnthis._list.IsFixedSize;
               }
           }
           publicoverrideboolIsSynchronized
           {
               get
               {
                   returntrue;
               }
           }
           publicoverrideobjectthis[intindex]
           {
               get
               {
                   objectresult;
                   lock(this._root)
                   {
                       result=this._list[index];
                   }
                   returnresult;
               }
               set
               {
                   lock(this._root)
                   {
                       this._list[index]=value;
                   }
               }
           }
           publicoverrideobjectSyncRoot
           {
               get
               {
                   returnthis._root;
               }
           }
           internalSyncArrayList(ArrayListlist)
               :base(false)
           {
               this._list=list;
               this._root=list.SyncRoot;
           }
           publicoverrideintAdd(objectvalue)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.Add(value);
               }
               returnresult;
           }
           publicoverridevoidAddRange(ICollectionc)
           {
               lock(this._root)
               {
                   this._list.AddRange(c);
               }
           }
           publicoverrideintBinarySearch(objectvalue)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.BinarySearch(value);
               }
               returnresult;
           }
           publicoverrideintBinarySearch(objectvalue,IComparercomparer)
           {
               intresult;
               lock(this._root)
              &nb sp;{
                   result=this._list.BinarySearch(value,comparer);
               }
               returnresult;
           }
           publicoverrideintBinarySearch(intindex,intcount,objectvalue,IComparercomparer)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.BinarySearch(index,count,value,comparer);
               }
               returnresult;
           }
           publicoverridevoidClear()
           {
               lock(this._root)
               {
                   this._list.Clear();
               }
           }
           publicoverrideobjectClone()
           {
               objectresult;
               lock(this._root)
               {
                   result=newArrayList.SyncArrayList((ArrayList)this._list.Clone());
               }
               returnresult;
           }
           publicoverrideboolContains(objectitem)
           {
               boolresult;
               lock(this._root)
               {
                   result=this._list.Contains(item);
               }
               returnresult;
           }
           publicoverridevoidCopyTo(Arrayarray)
       & nbsp;   {
               lock(this._root)
               {
                   this._list.CopyTo(array);
               }
           }
           publicoverridevoidCopyTo(Arrayarray,intindex)
           {
               lock(this._root)
               {
                   this._list.CopyTo(array,index);
               }
           }
           publicoverridevoidCopyTo(intindex,Arrayarray,intarrayIndex,intcount)
           {
               lock(this._root)
               {
                   this._list.CopyTo(index,array,arrayIndex,count);
               }
           }
           publicoverrideIEnumeratorGetEnumerator()
           {
               IEnumeratorenumerator;
               lock(this._root)
               {
                   enumerator=this._list.GetEnumerator();
               }
               returnenumerator;
           }
           publicoverrideIEnumeratorGetEnumerator(intindex,intcount)
           {
               IEnumeratorenumerator;
               lock(this._root)
               {
                   enumerator=this._list.GetEnumerator(index,count);
               }
               returnenumerator;
           }
           publicoverrideintIndexOf(objectvalue)
           {
    &n bsp;          intresult;
               lock(this._root)
               {
                   result=this._list.IndexOf(value);
               }
               returnresult;
           }
           publicoverrideintIndexOf(objectvalue,intstartIndex)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.IndexOf(value,startIndex);
               }
               returnresult;
           }
           publicoverrideintIndexOf(objectvalue,intstartIndex,intcount)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.IndexOf(value,startIndex,count);
               }
               returnresult;
           }
           publicoverridevoidInsert(intindex,objectvalue)
           {
               lock(this._root)
               {
                   this._list.Insert(index,value);
               }
           }
           publicoverridevoidInsertRange(intindex,ICollectionc)
           {
               lock(this._root)
               {
                   this._list.InsertRange(index,c);
               }
           }
           publicoverridei ntLastIndexOf(objectvalue)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.LastIndexOf(value);
               }
               returnresult;
           }
           publicoverrideintLastIndexOf(objectvalue,intstartIndex)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.LastIndexOf(value,startIndex);
               }
               returnresult;
           }
           publicoverrideintLastIndexOf(objectvalue,intstartIndex,intcount)
           {
               intresult;
               lock(this._root)
               {
                   result=this._list.LastIndexOf(value,startIndex,count);
               }
               returnresult;
           }
           publicoverridevoidRemove(objectvalue)
           {
               lock(this._root)
               {
                   this._list.Remove(value);
               }
           }
           publicoverridevoidRemoveAt(intindex)
           {
               lock(this._root)
               {
                   this._list.RemoveAt(index);
               }
      &nbsp ;    }
           publicoverridevoidRemoveRange(intindex,intcount)
           {
               lock(this._root)
               {
                   this._list.RemoveRange(index,count);
               }
           }
           publicoverridevoidReverse(intindex,intcount)
           {
               lock(this._root)
               {
                   this._list.Reverse(index,count);
               }
           }
           publicoverridevoidSetRange(intindex,ICollectionc)
           {
               lock(this._root)
               {
                   this._list.SetRange(index,c);
               }
           }
           publicoverrideArrayListGetRange(intindex,intcount)
           {
               ArrayListrange;
               lock(this._root)
               {
                   range=this._list.GetRange(index,count);
               }
               returnrange;
           }
           publicoverridevoidSort()
           {
               lock(this._root)
               {
                   this._list.Sort();
               }
           }
           publicoverridevoidSort(IComparercomparer)
           {
               lock(this._root)
      &nbs p;        {
                   this._list.Sort(comparer);
               }
           }
           publicoverridevoidSort(intindex,intcount,IComparercomparer)
           {
               lock(this._root)
               {
                   this._list.Sort(index,count,comparer);
               }
           }
           publicoverrideobject[]ToArray()
           {
               object[]result;
               lock(this._root)
               {
                   result=this._list.ToArray();
               }
               returnresult;
           }
           publicoverrideArrayToArray(Typetype)
           {
               Arrayresult;
               lock(this._root)
               {
                   result=this._list.ToArray(type);
               }
               returnresult;
           }
           publicoverridevoidTrimToSize()
           {
               lock(this._root)
               {
                   this._list.TrimToSize();
               }
           }
       }

ArrayList线程安全实现过程小结:定义ArrayList的私有实现SyncArrayList,子类内部通过lock同步构造实现线程安全,在ArrayList中通过Synchronized对外间接调用子类。 

二、Hashtable

同样,在C#早期版本中实现了线程安全的Hashtable,它也是早期开发中经常用到的缓存容器,可以通过下面的方式构造线程安全的哈希表:

varht=Hashtable.Synchronized(newHashtable());

同样地,我们从Synchronized方法入手,分析它的源代码看是如何实现线程安全的:
代码如下:
Synchronized       ///<summary>Returnsasynchronized(thread-safe)wrapperforthe<seecref=”T:System.Collections.Hashtable”/>.</summary>
       ///<returns>Asynchronized(thread-safe)wrapperforthe<seecref=”T:System.Collections.Hashtable”/>.</returns>
       ///<paramname=”table”>The<seecref=”T:System.Collections.Hashtable”/>tosynchronize.</param>
       ///<exceptioncref=”T:System.ArgumentNullException”>
       ///  <paramrefname=”table”/>isnull.</exception>
       ///<filterpriority>1</filterpriority>
       [HostProtection(SecurityAction.LinkDemand,Synchronization=true)]
       publicstaticHashtableSynchronized(Hashtabletable)
       {
           if(table==null)
           {
               thrownewArgumentNullException(“table”);
           }
           returnnewHashtable.SyncHashtable(table);
       }

继续跟进去,发现SyncHashtable是一个继承自Hashtable和IEnumerable接口的私有类,内部线程安全方法的实现经过分析,很多都是像下面这样lock(注意是lock哈希表的SyncRootObject实例对象而不是哈希表实例)一下完事:

lock(this._table.SyncRoot)

贴一下SyncHashtable的源码:
代码如下:
 [Serializable]
       privateclassSyncHashtable:Hashtable,IEnumerable
       {
           protectedHashtable_table;
           publicoverrideintCount
           {
               get
               {
                   returnthis._table.Count;
               }
           }
           publicoverrideboolIsReadOnly
           {
               get
               {
                   returnthis._table.IsReadOnly;
               }
           }
           publicoverrideboolIsFixedSize
           {
               get
               {
                   returnthis._table.IsFixedSize;
               }
           }
           publicoverrideboolIsSynchronized
           {
               get
               {
                   returntrue;
               }
           }
           publicoverrideobjectthis[objectkey]
           {
               [TargetedPatchingOptOut(“PerformancecriticaltoinlineacrossNGenimageboundaries”)]
               get
               {
                   returnthis._table[key];
               }
               set
               {
                   lock(this._table.SyncR oot)
                   {
                       this._table[key]=value;
                   }
               }
           }
           publicoverrideobjectSyncRoot
           {
               get
               {
                   returnthis._table.SyncRoot;
               }
           }
           publicoverrideICollectionKeys
           {
               get
               {
                   ICollectionkeys;
                   lock(this._table.SyncRoot)
                   {
                       keys=this._table.Keys;
                   }
                   returnkeys;
               }
           }
           publicoverrideICollectionValues
           {
               get
               {
                   ICollectionvalues;
                   lock(this._table.SyncRoot)
                   {
                       values=this._table.Values;
                   }
                   returnvalues;
   &n

标签: 容器 线程 线程安全 方法

C++中extern "C"的用法

C++与C的差异分析

上述就是C#学习教程:深入线程安全容器的实现方法分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/904671.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐