我有一个Dictionary<object1, List<object2>
(我为我的结构做了一个抽象化,这有点复杂了。)
字典中的列表在非并行上下文中初始化,但向列表中添加新元素需要线程安全方法。删除项目不会发生(字典对象将在事务结束时处理)。 此外,键值对仅在初始化时添加,因此在工作期间不会在字典中添加或删除键,只会更新值。
我无法使用concurent集合,我陷入了旧的.NET Framework。
起初我用ReadWriteSlimlock
锁定了整个字典。嗯,这是非常糟糕的表现。有很多添加操作正在发生,他们只是等待另一个。仅锁定每个列表是一个更好的解决方案,因为至少我正在为每个键并行执行操作。
此外,添加操作不简单list.Add(object2)
,在添加时需要在线程安全区域中进行一些其他复杂操作。
但我不知道实施它的最佳方法是什么:
lock(dictionary.Value)
?ReadWriteSlimlock
字典(每个密钥一个字符)?答案 0 :(得分:2)
另一个解决方案可能是实现你的concurent List<object>
类。
类似的东西:
public class ConcurentList {
private object sync = new object();
private List<object> realList = new List<object>();
public void Add(object o) {
lock(sync){
realList.Add(o);
}
}
/** ADD OTHERE METHODS IMPEMENTATION IF NEED **/
}
并在字典中有:
Dictionary<object1, ConcurentList>
为什么封装而不是扩展List<object>
,因为Add
方法不是虚拟的,所以你可以“覆盖”它的唯一方法是使用{{1 }}}关键字,如果在完全相同的类型上使用,则保证仅被称为 ,这意味着如果将列表转换为基础,则不会调用它,所以洞建筑将失败。
通过封装,您只向调用者提供一个控制所有内容的方法。
不知道这个解决方案是否符合您的需求,但希望它能为您提供一些管理内容的提示。
答案 1 :(得分:1)
为什么不编写Dictionary<>
和List<>
自己的并发线程安全变体?这就是我为.NET 2所做的。
我个人选择了ReaderWriterLockSlim
,因为它允许你根据访问模式控制锁定,而且大多数情况下我的列表都是从写入的内容中读取的。
但是,您正在进行大量添加,因此您可能需要同时尝试(lock
和ReaderWriterLockSlim
)并查看哪些效果更好。
答案 2 :(得分:1)
如果从列表中读取与写入同时发生,则为每个字典条目构造ReaderWriterLockSlim
对象将是最佳解决方案,因为多个读取器将能够在同一列表上同时进行。它只比使用lock(key)
稍微困难一点,并且在比其他列表更频繁地读取少量列表的情况下,它有可能提高性能。
如果你走ReaderWriterLockSlim
路线,最好将列表和锁包装在一个类中,而不是仅为读写器锁创建一个单独的字典:
class LockableList {
public ReaderWriterLockSlim RwLock {get;private set;}
public List<object2> Data {get;private set;}
public LockableList() {
RwLock = new ReaderWriterLockSlim();
Data = new List<object2>();
}
}
...
Dictionary<object1,LockableList> myDictionary;
组合列表和外观可让您查找字典条目一次,将其锁定以供阅读或适当写入,并使用相关列表进行工作。