我们认真一点就会发现System.Collections名称空间中几乎所有的容器类帮助文档都有类似下面的一段话:
Hashtable
Hashtable 是线程安全的,可由多个读取器线程或一个写入线程使用。多线程使用时,如果任何一个线程执行写入(更新)操作,它都不是线程安全的。若要支持多个编写器,如果没有任何线程在读取 Hashtable 对象,则对 Hashtable 的所有操作都必须通过Synchronized方法返回的包装完成。
ArrayList
只要集合未修改,ArrayList 就可以同时支持多个阅读器。若要保证 ArrayList 的线程安全,则必须通过由 Synchronized方法返回的包装来执行所有操作。
用 Reflector 查看Hashtable.Synchronized方法。
[HostProtection(SecurityAction.LinkDemand, Synchronization
=
true
)]
public static Hashtable Synchronized(Hashtable table)
{
if (table == null )
{
throw new ArgumentNullException( " table " );
}
return new Hashtable.SyncHashtable(table);
}
public static Hashtable Synchronized(Hashtable table)
{
if (table == null )
{
throw new ArgumentNullException( " table " );
}
return new Hashtable.SyncHashtable(table);
}
我们发现该方法创建了一个Hashtable的子类SyncHashtable实例。
View Code
using
System;
using System.Collections;
using System.Reflection;
using System.Runtime.Serialization;
[Serializable]
private class SyncHashtable : Hashtable
{
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()
{
object obj1;
lock ( this ._table.SyncRoot)
{
obj1 = Hashtable.Synchronized((Hashtable) this ._table.Clone());
}
return obj1;
}
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)
{
bool flag1;
lock ( this ._table.SyncRoot)
{
flag1 = this ._table.ContainsValue(key);
}
return flag1;
}
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();
}
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
{
ICollection collection1;
lock ( this ._table.SyncRoot)
{
collection1 = this ._table.Keys;
}
return collection1;
}
}
public override object SyncRoot
{
get
{
return this ._table.SyncRoot;
}
}
public override ICollection Values
{
get
{
ICollection collection1;
lock ( this ._table.SyncRoot)
{
collection1 = this ._table.Values;
}
return collection1;
}
}
protected Hashtable _table;
}
using System.Collections;
using System.Reflection;
using System.Runtime.Serialization;
[Serializable]
private class SyncHashtable : Hashtable
{
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()
{
object obj1;
lock ( this ._table.SyncRoot)
{
obj1 = Hashtable.Synchronized((Hashtable) this ._table.Clone());
}
return obj1;
}
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)
{
bool flag1;
lock ( this ._table.SyncRoot)
{
flag1 = this ._table.ContainsValue(key);
}
return flag1;
}
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();
}
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
{
ICollection collection1;
lock ( this ._table.SyncRoot)
{
collection1 = this ._table.Keys;
}
return collection1;
}
}
public override object SyncRoot
{
get
{
return this ._table.SyncRoot;
}
}
public override ICollection Values
{
get
{
ICollection collection1;
lock ( this ._table.SyncRoot)
{
collection1 = this ._table.Values;
}
return collection1;
}
}
protected Hashtable _table;
}
原来.net Framework已经替我们写好了lock方法的包装。可以解决多线程的问题。