c#中ConcurrentDictionary和字典本身的分层锁策略
本文关键字:分层 策略 ConcurrentDictionary 字典 | 更新日期: 2023-09-27 18:02:38
我被迫在代码中使用并发字典,其中'key'是一个对象,'value'是一个int,表示第三方库提供的该对象的唯一连接参数。连接参数被存储,当通过第三方库抛出事件时,唯一键是事件参数之一,我们可以使用它找到正确的对象来处理进一步的代码。
我的问题如下:
-
有时候,并发字典需要更新一个需要处理的对象列表。
-
单个对象在处理期间需要锁,因为抛出的事件必须顺序执行,而不是并行执行。(这已成为最近的要求,因为我们看到任务有时在不同线程上并行处理,并在保存到数据库时获得OptimisticConcurrencyException。)
对字典中的单个对象应用锁不是问题,但是当我试图在刷新列表的同时从字典中删除当前锁定的对象时,会出现一个新的问题。
我曾尝试编写一个小型控制台应用程序,按顺序执行有问题的步骤,"Monitor.Exit(key);"行抛出异常"对象同步方法从未同步的代码块中调用"。
class Program
{
static ConcurrentDictionary<object, int> _handles = new ConcurrentDictionary<object, int>();
static void Main(string[] args)
{
object lockableKey = 'key';
_handles.AddOrUpdate(lockableKey, 10, (oldkey, oldvalue) => 10);
var key = _handles.Keys.FirstOrDefault(h => h == lockableKey);
Console.WriteLine("key found, beginning to lock");
Monitor.Enter(key);
Console.WriteLine("key locked");
////Console.WriteLine("applying outer lock, hoping for code to stop executing");
////Monitor.Enter(_handles);
Console.WriteLine("Removing key from dictionary");
int dummy;
_handles.TryRemove(lockableKey, out dummy);
Console.WriteLine("Removing lock from object removed from dictionary");
Monitor.Exit(key);
}
所以问题是,有没有一种方法可以将锁应用于外部字典,像主锁一样,等待字典中对象的所有子锁完成执行,然后刷新字典并继续处理传入的事件?
感谢大家的帮助,似乎之前的评论被删除了,帮助我找到了答案,所以我不能给它应得的功劳。
我实现了'ReaderWriterLockSlim'类。这允许多个读线程同时处理,但只能处理一个写线程。所以所有的处理线程都取出了一个读锁,但是更新字典的线程取出了一个写锁。写锁等待所有读锁完成,但也优先于所有读锁。因此,一旦写锁被请求,读锁必须等到写锁完成后才能进入临界区。
除此之外,在reader线程中,我还应用了一个Monitor。