在.net 2.0中,ArrayList和HashTable都有一个封装了同步功能的新实现.
它们可以通过ArrayList.Synchronized方法或者HashTable.Synchronized方法来获得.
下面是方法的具体实现:
代码
[HostProtection(SecurityAction.LinkDemand, Synchronization
=
true
)]
public static ArrayList Synchronized(ArrayList list)
{
if (list == null )
{
throw new ArgumentNullException( " list " );
}
return new SyncArrayList(list);
}
[HostProtection(SecurityAction.LinkDemand, Synchronization = true )]
public static IList Synchronized(IList list)
{
if (list == null )
{
throw new ArgumentNullException( " list " );
}
return new SyncIList(list);
}
[HostProtection(SecurityAction.LinkDemand, Synchronization = true )]
public static Hashtable Synchronized(Hashtable table)
{
if (table == null )
{
throw new ArgumentNullException( " table " );
}
return new SyncHashtable(table);
}
public static ArrayList Synchronized(ArrayList list)
{
if (list == null )
{
throw new ArgumentNullException( " list " );
}
return new SyncArrayList(list);
}
[HostProtection(SecurityAction.LinkDemand, Synchronization = true )]
public static IList Synchronized(IList list)
{
if (list == null )
{
throw new ArgumentNullException( " list " );
}
return new SyncIList(list);
}
[HostProtection(SecurityAction.LinkDemand, Synchronization = true )]
public static Hashtable Synchronized(Hashtable table)
{
if (table == null )
{
throw new ArgumentNullException( " table " );
}
return new SyncHashtable(table);
}
里面的SyncHashtable之流便是同步的HashTable了,
再看看它的实现
代码
[Serializable]
private class SyncHashtable : Hashtable
{
// Fields
protected Hashtable _table;
// Methods
internal SyncHashtable(Hashtable table) : base ( false )
{
this ._table = table;
}
internal SyncHashtable(SerializationInfo info, StreamingContext context) : base (info, context)
{
this ._table = (Hashtable) info.GetValue( " ParentTable " , typeof (Hashtable));
if ( this ._table == null )
{
throw new SerializationException(Environment.GetResourceString( " Serialization_InsufficientState " ));
}
}
public override void Add( object key, object value)
{
lock ( this ._table.SyncRoot)
{
this ._table.Add(key, value);
}
}
public override void Clear()
{
lock ( this ._table.SyncRoot)
{
this ._table.Clear();
}
}
public override object Clone()
{
lock ( this ._table.SyncRoot)
{
return Hashtable.Synchronized((Hashtable) this ._table.Clone());
}
}
public override bool Contains( object key)
{
return this ._table.Contains(key);
}
public override bool ContainsKey( object key)
{
return this ._table.ContainsKey(key);
}
public override bool ContainsValue( object key)
{
lock ( this ._table.SyncRoot)
{
return this ._table.ContainsValue(key);
}
}
public override void CopyTo(Array array, int arrayIndex)
{
lock ( this ._table.SyncRoot)
{
this ._table.CopyTo(array, arrayIndex);
}
}
public override IDictionaryEnumerator GetEnumerator()
{
return this ._table.GetEnumerator();
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null )
{
throw new ArgumentNullException( " info " );
}
info.AddValue( " ParentTable " , this ._table, typeof (Hashtable));
}
public override void OnDeserialization( object sender)
{
}
public override void Remove( object key)
{
lock ( this ._table.SyncRoot)
{
this ._table.Remove(key);
}
}
internal override KeyValuePairs[] ToKeyValuePairsArray()
{
return this ._table.ToKeyValuePairsArray();
}
// Properties
public override int Count
{
get
{
return this ._table.Count;
}
}
public override bool IsFixedSize
{
get
{
return this ._table.IsFixedSize;
}
}
public override bool IsReadOnly
{
get
{
return this ._table.IsReadOnly;
}
}
public override bool IsSynchronized
{
get
{
return true ;
}
}
public override object this [ object key]
{
get
{
return this ._table[key];
}
set
{
lock ( this ._table.SyncRoot)
{
this ._table[key] = value;
}
}
}
public override ICollection Keys
{
get
{
lock ( this ._table.SyncRoot)
{
return this ._table.Keys;
}
}
}
public override object SyncRoot
{
get
{
return this ._table.SyncRoot;
}
}
public override ICollection Values
{
get
{
lock ( this ._table.SyncRoot)
{
return this ._table.Values;
}
}
}
}
private class SyncHashtable : Hashtable
{
// Fields
protected Hashtable _table;
// Methods
internal SyncHashtable(Hashtable table) : base ( false )
{
this ._table = table;
}
internal SyncHashtable(SerializationInfo info, StreamingContext context) : base (info, context)
{
this ._table = (Hashtable) info.GetValue( " ParentTable " , typeof (Hashtable));
if ( this ._table == null )
{
throw new SerializationException(Environment.GetResourceString( " Serialization_InsufficientState " ));
}
}
public override void Add( object key, object value)
{
lock ( this ._table.SyncRoot)
{
this ._table.Add(key, value);
}
}
public override void Clear()
{
lock ( this ._table.SyncRoot)
{
this ._table.Clear();
}
}
public override object Clone()
{
lock ( this ._table.SyncRoot)
{
return Hashtable.Synchronized((Hashtable) this ._table.Clone());
}
}
public override bool Contains( object key)
{
return this ._table.Contains(key);
}
public override bool ContainsKey( object key)
{
return this ._table.ContainsKey(key);
}
public override bool ContainsValue( object key)
{
lock ( this ._table.SyncRoot)
{
return this ._table.ContainsValue(key);
}
}
public override void CopyTo(Array array, int arrayIndex)
{
lock ( this ._table.SyncRoot)
{
this ._table.CopyTo(array, arrayIndex);
}
}
public override IDictionaryEnumerator GetEnumerator()
{
return this ._table.GetEnumerator();
}
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null )
{
throw new ArgumentNullException( " info " );
}
info.AddValue( " ParentTable " , this ._table, typeof (Hashtable));
}
public override void OnDeserialization( object sender)
{
}
public override void Remove( object key)
{
lock ( this ._table.SyncRoot)
{
this ._table.Remove(key);
}
}
internal override KeyValuePairs[] ToKeyValuePairsArray()
{
return this ._table.ToKeyValuePairsArray();
}
// Properties
public override int Count
{
get
{
return this ._table.Count;
}
}
public override bool IsFixedSize
{
get
{
return this ._table.IsFixedSize;
}
}
public override bool IsReadOnly
{
get
{
return this ._table.IsReadOnly;
}
}
public override bool IsSynchronized
{
get
{
return true ;
}
}
public override object this [ object key]
{
get
{
return this ._table[key];
}
set
{
lock ( this ._table.SyncRoot)
{
this ._table[key] = value;
}
}
}
public override ICollection Keys
{
get
{
lock ( this ._table.SyncRoot)
{
return this ._table.Keys;
}
}
}
public override object SyncRoot
{
get
{
return this ._table.SyncRoot;
}
}
public override ICollection Values
{
get
{
lock ( this ._table.SyncRoot)
{
return this ._table.Values;
}
}
}
}
这下明白了吧,就是给ArrayList和HashTable的访问方法加了个lock,
不过,这可比我们自己手写还是要靠谱的多..(注意:在进行轶代时,并不是线程安全的。如果要求绝对的线程安全,可以自行lock对象的SyncRoot)
不过有些场景可是不能lock太过的,比如读写比很高的场景(很少写,而读很多)
不过不用担心,并发环境下的缓存容器性能优化(上):不可变的哈希表
老赵的这篇文章已经有了很好的解决办法了.