3

我有一个Dictionary<object1, List<object2>(我为我的结构做的抽象,它有点复杂)。

字典中的列表在非并行上下文中初始化,但是向列表中添加新元素需要线程安全的方法。不会删除项目(字典对象将在事务结束时处理)。此外,键值对仅在初始化时添加,因此在工作期间不会从字典中添加或删除键,仅更新值。

我不能使用并发集合,我被困在一个旧的 .NET 框架中。

起初我用ReadWriteSlimlock. 好吧,这是非常糟糕的表现。有许多添加操作发生,他们只是等待另一个。仅锁定每个列表是一个更好的解决方案,因为至少我正在为每个键并行做一些事情。另外,加法操作并不简单list.Add(object2),加法时还需要在线程安全区进行一些其他复杂的操作。

但我不知道实现它的最佳方法是什么:

  1. lock(dictionary.Value)?
  2. 使用字典ReadWriteSlimlock(每个键一个)?
  3. 还有其他更好的解决方案吗?
4

3 回答 3

2

另一种解决方案可能是实现你的并发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方法不是虚拟的,所以你可以“覆盖”它的唯一方法是使用关键字,它保证只有完全相同的类型new上使用时才会被调用,这意味着如果你转换列表到基地,它不会被调用,所以洞架构会失败。

通过封装,你只给调用者一个方法,你可以控制一切。

不知道这个解决方案是否符合您的需求,但希望它能给您一些关于如何管理东西的提示。

于 2013-01-17T11:49:45.737 回答
1

为什么不编写自己的和的并发线程安全变Dictionary<>List<>?这就是我为 .NET 2 所做的。

我个人选择了,ReaderWriterLockSlim因为它允许您根据访问模式控制锁定,并且在大多数情况下,我的列表是从被写入的更多内容中读取的。

但是,您正在添加大量内容,因此您可能希望同时尝试 (lockReaderWriterLockSlim) 并查看哪个性能更好。

于 2013-01-17T11:42:47.210 回答
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;

将列表和外观结合起来可以让您查找字典条目一次,根据需要锁定它以供读取或写入,并使用关联的列表进行工作。

于 2013-01-17T11:49:01.893 回答