积极答复者
如何在 Dictionary<> 上面实现,写同步锁,读共享锁。

问题
-
一般在多线程操作字典集合的时候,会不停的遍历,但是也会在某几个线程中对字典进行修改,如何做到在读字典的时候都是共享的,而在写的时候进行锁定,直到写完之后,才可以继续共享锁。
Sherrys- 已移动 Sheng Jiang 蒋晟Moderator 2009年7月16日 21:13 软件设计问题 (发件人:Visual C#)
答案
-
你好 这是我自己写的一个实现 使用了 3.5 的lock slim
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ComponentModel.Design; using System.Runtime.InteropServices; using System.Diagnostics; using System.Threading; using System.Security.Permissions; namespace System.Collections.Generic.Sync { public class SyncDictionary<TKey, TValue> : Dictionary<TKey, TValue> { private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); public new void Add(TKey key, TValue value) { _lock.EnterWriteLock(); base.Add(key, value); _lock.ExitWriteLock(); } public new void Clear() { _lock.EnterWriteLock(); base.Clear(); _lock.ExitWriteLock(); } public new bool ContainsKey(TKey key) { _lock.EnterReadLock(); var rv = base.ContainsKey(key); _lock.ExitReadLock(); return rv; } public new bool ContainsValue(TValue value) { _lock.EnterReadLock(); var rv = base.ContainsValue(value); _lock.ExitReadLock(); return rv; } public new Dictionary<TKey, TValue>.Enumerator GetEnumerator() { _lock.EnterReadLock(); var rv = new Dictionary<TKey, TValue>(this).GetEnumerator(); _lock.ExitReadLock(); return rv; } public new bool Remove(TKey key) { _lock.EnterWriteLock(); var rv = base.Remove(key); _lock.ExitWriteLock(); return rv; } public new bool TryGetValue(TKey key, out TValue value) { _lock.EnterReadLock(); var rv = base.TryGetValue(key, out value); _lock.ExitReadLock(); return rv; } public new int Count { get { _lock.EnterReadLock(); var rv = base.Count; _lock.ExitReadLock(); return rv; } } public new TValue this[TKey key] { get { _lock.EnterReadLock(); var rv = base[key]; _lock.ExitReadLock(); return rv; } set { _lock.EnterWriteLock(); base[key] = value; _lock.ExitWriteLock(); } } public new Generic.Dictionary <TKey, TValue>.KeyCollection Keys { get { _lock.EnterReadLock(); var rv = base.Keys; _lock.ExitReadLock(); return rv; } } public new Generic.Dictionary<TKey, TValue>.ValueCollection Values { get { _lock.EnterReadLock(); var rv = base.Values; _lock.ExitReadLock(); return rv; } } } }
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已标记为答案 Sherrys 2009年7月16日 5:35
-
如果你的工程中 这个字典不能修改了 可以用下面这个adepter 把原来的字典封装起来 以后访问这个引用就可以实现读写锁
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ComponentModel.Design; using System.Runtime.InteropServices; using System.Diagnostics; using System.Threading; using System.Security.Permissions; namespace System.Collections.Generic.Sync { public class SyncDictionaryAdapter<TKey, TValue> : IDictionary<TKey, TValue> { private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); Dictionary<TKey, TValue> BaseDictionary { get; set; } private ICollection<KeyValuePair<TKey, TValue>> BaseCollection { get { return (ICollection<KeyValuePair<TKey, TValue>>)BaseDictionary; } } public SyncDictionaryAdapter(Dictionary<TKey, TValue> Dictionary) { BaseDictionary = Dictionary; } #region IDictionary<TKey,TValue> Members public void Add(TKey key, TValue value) { _lock.EnterWriteLock(); BaseDictionary.Add(key, value); _lock.ExitWriteLock(); } public bool ContainsKey(TKey key) { _lock.EnterReadLock(); var rv = BaseDictionary .ContainsKey(key); _lock.ExitReadLock(); return rv; } public ICollection<TKey> Keys { get { _lock.EnterReadLock(); var rv = BaseDictionary.Keys; _lock.ExitReadLock(); return rv; } } public bool Remove(TKey key) { _lock.EnterWriteLock(); var rv = BaseDictionary.Remove(key); _lock.ExitWriteLock(); return rv; } public bool TryGetValue(TKey key, out TValue value) { _lock.EnterReadLock(); var rv = BaseDictionary.TryGetValue(key, out value); _lock.ExitReadLock(); return rv; } public ICollection<TValue> Values { get { _lock.EnterReadLock(); var rv = BaseDictionary.Values; _lock.ExitReadLock(); return rv; } } public TValue this[TKey key] { get { _lock.EnterReadLock(); var rv = BaseDictionary[key]; _lock.ExitReadLock(); return rv; } set { _lock.EnterWriteLock(); BaseDictionary[key] = value; _lock.ExitWriteLock(); } } #endregion #region ICollection<KeyValuePair<TKey,TValue>> Members public void Add(KeyValuePair<TKey, TValue> item) { _lock.EnterWriteLock(); BaseCollection.Add(item); _lock.ExitWriteLock (); } public void Clear() { _lock.EnterWriteLock(); BaseCollection.Clear (); _lock.ExitWriteLock(); } public bool Contains(KeyValuePair<TKey, TValue> item) { _lock.EnterReadLock (); var rv = BaseCollection.Contains(item); _lock.ExitReadLock (); return rv; } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _lock.EnterReadLock(); BaseCollection.CopyTo(array, arrayIndex); _lock.ExitReadLock(); } public int Count { get { _lock.EnterReadLock(); var rv = BaseCollection.Count; _lock.ExitReadLock(); return rv; } } public bool IsReadOnly { get { return BaseCollection.IsReadOnly; } } public bool Remove(KeyValuePair<TKey, TValue> item) { _lock.EnterWriteLock (); var rv = BaseCollection.Remove(item); _lock.ExitWriteLock(); return rv; } #endregion #region IEnumerable<KeyValuePair<TKey,TValue>> Members public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return BaseDictionary.GetEnumerator(); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return BaseDictionary.GetEnumerator(); } #endregion } }
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已建议为答案 韦恩卑鄙 waywaModerator 2009年7月16日 5:16
- 已标记为答案 Sherrys 2009年7月16日 5:46
全部回复
-
你好 这是我自己写的一个实现 使用了 3.5 的lock slim
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ComponentModel.Design; using System.Runtime.InteropServices; using System.Diagnostics; using System.Threading; using System.Security.Permissions; namespace System.Collections.Generic.Sync { public class SyncDictionary<TKey, TValue> : Dictionary<TKey, TValue> { private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); public new void Add(TKey key, TValue value) { _lock.EnterWriteLock(); base.Add(key, value); _lock.ExitWriteLock(); } public new void Clear() { _lock.EnterWriteLock(); base.Clear(); _lock.ExitWriteLock(); } public new bool ContainsKey(TKey key) { _lock.EnterReadLock(); var rv = base.ContainsKey(key); _lock.ExitReadLock(); return rv; } public new bool ContainsValue(TValue value) { _lock.EnterReadLock(); var rv = base.ContainsValue(value); _lock.ExitReadLock(); return rv; } public new Dictionary<TKey, TValue>.Enumerator GetEnumerator() { _lock.EnterReadLock(); var rv = new Dictionary<TKey, TValue>(this).GetEnumerator(); _lock.ExitReadLock(); return rv; } public new bool Remove(TKey key) { _lock.EnterWriteLock(); var rv = base.Remove(key); _lock.ExitWriteLock(); return rv; } public new bool TryGetValue(TKey key, out TValue value) { _lock.EnterReadLock(); var rv = base.TryGetValue(key, out value); _lock.ExitReadLock(); return rv; } public new int Count { get { _lock.EnterReadLock(); var rv = base.Count; _lock.ExitReadLock(); return rv; } } public new TValue this[TKey key] { get { _lock.EnterReadLock(); var rv = base[key]; _lock.ExitReadLock(); return rv; } set { _lock.EnterWriteLock(); base[key] = value; _lock.ExitWriteLock(); } } public new Generic.Dictionary <TKey, TValue>.KeyCollection Keys { get { _lock.EnterReadLock(); var rv = base.Keys; _lock.ExitReadLock(); return rv; } } public new Generic.Dictionary<TKey, TValue>.ValueCollection Values { get { _lock.EnterReadLock(); var rv = base.Values; _lock.ExitReadLock(); return rv; } } } }
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已标记为答案 Sherrys 2009年7月16日 5:35
-
如果你的工程中 这个字典不能修改了 可以用下面这个adepter 把原来的字典封装起来 以后访问这个引用就可以实现读写锁
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; using System.ComponentModel.Design; using System.Runtime.InteropServices; using System.Diagnostics; using System.Threading; using System.Security.Permissions; namespace System.Collections.Generic.Sync { public class SyncDictionaryAdapter<TKey, TValue> : IDictionary<TKey, TValue> { private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); Dictionary<TKey, TValue> BaseDictionary { get; set; } private ICollection<KeyValuePair<TKey, TValue>> BaseCollection { get { return (ICollection<KeyValuePair<TKey, TValue>>)BaseDictionary; } } public SyncDictionaryAdapter(Dictionary<TKey, TValue> Dictionary) { BaseDictionary = Dictionary; } #region IDictionary<TKey,TValue> Members public void Add(TKey key, TValue value) { _lock.EnterWriteLock(); BaseDictionary.Add(key, value); _lock.ExitWriteLock(); } public bool ContainsKey(TKey key) { _lock.EnterReadLock(); var rv = BaseDictionary .ContainsKey(key); _lock.ExitReadLock(); return rv; } public ICollection<TKey> Keys { get { _lock.EnterReadLock(); var rv = BaseDictionary.Keys; _lock.ExitReadLock(); return rv; } } public bool Remove(TKey key) { _lock.EnterWriteLock(); var rv = BaseDictionary.Remove(key); _lock.ExitWriteLock(); return rv; } public bool TryGetValue(TKey key, out TValue value) { _lock.EnterReadLock(); var rv = BaseDictionary.TryGetValue(key, out value); _lock.ExitReadLock(); return rv; } public ICollection<TValue> Values { get { _lock.EnterReadLock(); var rv = BaseDictionary.Values; _lock.ExitReadLock(); return rv; } } public TValue this[TKey key] { get { _lock.EnterReadLock(); var rv = BaseDictionary[key]; _lock.ExitReadLock(); return rv; } set { _lock.EnterWriteLock(); BaseDictionary[key] = value; _lock.ExitWriteLock(); } } #endregion #region ICollection<KeyValuePair<TKey,TValue>> Members public void Add(KeyValuePair<TKey, TValue> item) { _lock.EnterWriteLock(); BaseCollection.Add(item); _lock.ExitWriteLock (); } public void Clear() { _lock.EnterWriteLock(); BaseCollection.Clear (); _lock.ExitWriteLock(); } public bool Contains(KeyValuePair<TKey, TValue> item) { _lock.EnterReadLock (); var rv = BaseCollection.Contains(item); _lock.ExitReadLock (); return rv; } public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { _lock.EnterReadLock(); BaseCollection.CopyTo(array, arrayIndex); _lock.ExitReadLock(); } public int Count { get { _lock.EnterReadLock(); var rv = BaseCollection.Count; _lock.ExitReadLock(); return rv; } } public bool IsReadOnly { get { return BaseCollection.IsReadOnly; } } public bool Remove(KeyValuePair<TKey, TValue> item) { _lock.EnterWriteLock (); var rv = BaseCollection.Remove(item); _lock.ExitWriteLock(); return rv; } #endregion #region IEnumerable<KeyValuePair<TKey,TValue>> Members public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { return BaseDictionary.GetEnumerator(); } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { return BaseDictionary.GetEnumerator(); } #endregion } }
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已建议为答案 韦恩卑鄙 waywaModerator 2009年7月16日 5:16
- 已标记为答案 Sherrys 2009年7月16日 5:46
-
我给你的就是更新锁全部 读取互相不锁的代码 看代码 readwritelockslim 就是你要的
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。- 已建议为答案 韦恩卑鄙 waywaModerator 2009年7月16日 5:16
-
我给你的就是更新锁全部 读取互相不锁的代码 看代码 readwritelockslim 就是你要的
答案900, 目标五颗星 Aurvana Air, 音乐真的是随风飘来的 凉宫春日 永无止境的八月 你到底什么时候结束阿。。。。
你给的正是我需要的,就是这个 Slim 。
不过请问下,如果使用你第一个代码片段,如果所有的 Dic 都使用 new SyncDictionary() 是否会有问题。?
关于你第二个进行封装,这样跟第一种的区别在哪里?因为还是可以对 Dic 进行修改,所以不是很理解。
Sherrys
请问,基于第二种 adapter 的写法,为何要使用接口 ICollection 来做引用呢,这样做对于使用 Dic 来说有什么好处?那样本来 Dic 的一些泛型方法,比如 ContainsKey 怎么才能使用?
Sherrys