请教自定义Dictionary类如何在类内实现线程同步的问题谢谢!
微软的Dictionary的实例成员是不支持线程安全的,因此我自定义了一个Dictionary,但在进行枚举操作的时候无法进行锁定,请大家帮帮我想想办法,代码如下:
- C# code
public class DictionaryEx<Tkey, Tvalue> { public DictionaryEx() { mDic = new Dictionary<Tkey, Tvalue>(); } private Dictionary<Tkey, Tvalue> mDic; public void Add(Tkey Key, Tvalue Item) { ICollection ic = mDic.Values; lock (ic.SyncRoot) {mDic.Add(Key, Item); } } public Dictionary<Tkey, Tvalue>.Enumerator GetEnumerator() { ICollection ic = mDic.Values; lock (ic.SyncRoot)//这一句根本起不了作用 { return mDic.GetEnumerator(); } } public Dictionary<Tkey, Tvalue>.ValueCollection Values { get { return mDic.Values; } } }
[解决办法]
关注
目前我知道的方法就是某人说的副本方式
[解决办法]
http://devplanet.com/blogs/brianr/archive/2008/09/26/thread-safe-dictionary-in-net.aspx
[解决办法]
关于枚举,如果你加锁,那效率太低了,别的线程一定要等你枚举完了,才能访问。往往我们做枚举不一定非到要得到最精确的数据。你可以先获取它的所有keys,然后遍历keys去访问里面的数据。
下面是本人写的一个县城安全的dictionary,供参考,请注意我有一个AllKeys的属性,这个就是获取所有keys,然后外面的程序从这个属性获取的数据去遍历就可以了,之所以加上一个keysisnew,是因为如果数据量大,Keys.ToArray()也会耗费较长时间,所以只有发生项的添加和减少时,才会重新生成keys集合。
- C# code
public class SynchronizedDictionary<TKey, TValue> { private readonly object _syncRoot = new object(); private readonly Dictionary<TKey, TValue> _dictionaryBase; TKey[] _allKeys = new TKey[0]; bool _keysIsNew = false; public SynchronizedDictionary() { _dictionaryBase = new Dictionary<TKey, TValue>(); } internal Dictionary<TKey, TValue> DictionaryBase { get { return _dictionaryBase; } } public void Add(TKey key, TValue val) { this[key] = val; _keysIsNew = true; } public bool Remove(TKey key) { lock (_syncRoot) { if (_dictionaryBase.Remove(key)) { _keysIsNew = true; return true; } } return false; } public void Clear() { lock (_syncRoot) { _dictionaryBase.Clear(); } _keysIsNew = true; } public bool ContainsKey(TKey key) { lock (_syncRoot) { return _dictionaryBase.ContainsKey(key); } } public Dictionary<TKey, TValue>.KeyCollection Keys { get { lock (_syncRoot) { return _dictionaryBase.Keys; } } } public Dictionary<TKey, TValue>.ValueCollection Values { get { lock (_syncRoot) { return _dictionaryBase.Values; } } } public TKey[] AllKeys { get { if (_keysIsNew) { lock (_syncRoot) { if (_keysIsNew) { _allKeys = _dictionaryBase.Keys.ToArray(); _keysIsNew = false; } } } return _allKeys; } } public TValue this[TKey key] { get { TValue v = default(TValue); try { _dictionaryBase.TryGetValue(key, out v); } catch (System.Exception ex) { LogManager.WriteErrorWithDescription("SynchronizedDictionary_Get:", ex); lock (_syncRoot) { _dictionaryBase.TryGetValue(key, out v); } } return v; } set { lock (_syncRoot) { _dictionaryBase[key] = value; } } } public int Count { get { lock (_syncRoot) { return _dictionaryBase.Count; } } } public object SyncRoot { get { return _syncRoot; } } }
[解决办法]
如果采用产生副本的方法,对于客户代码来说,就不能象访问内置的Dictionary一样来访问自定义的Dictionary了
什么意思?
[解决办法]
将Dictionary包成HashTable试试?
- C# code
Hashtable hash = Hashtable.Synchronized(new Hashtable((IDictionary)mDic));
[解决办法]
发生冲突的部分无非是在往Dictionary写值的时候,所以在离写Dictionary最近的地方加一个锁
syncRoot是自定义SafteDictionary内的互斥对象,哪个线程拿到它才可以对内部的Dictionary进行操作。
比如new Dictionary().Add加一个syncRoot的锁,变成
public void Add(TKey key, TValue value)
{
lock (syncRoot)
{
d.Add(key, value);
}
}
同一个时间点只能有一个线程能够访问d.Add(key, value);
示例下载:
http://files.cnblogs.com/kiddo/MultiThread.rar
以上信息来自:http://www.cnblogs.com/kiddo/archive/2008/09/25/1299089.html
LZ感兴趣可以看看
[解决办法]
我已上传到资源里面去下吧
http://download.csdn.net/source/1108764
[解决办法]
所谓的线程安全是站在某个具体环境下说的。而具体环境是由客户代码来构建的,因此安全一般由客户代码来负责......
对一个对象而言, 希望把它做成绝对安全的, 往往要么是花的设计成本太大,要么是性能仆街。
[解决办法]
[解决办法]
不推荐在多线程环境下使用共享的Dictionary进行写操作
可以使用一种相对代价较小的ReaderWriterLock来实现,
这种锁不会阻塞多个并行的读操作,
只会在有写操作进行时候才阻塞所有线程。