最近写了个小程序用到了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);
}
  ; }
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