英文:
Trying to keep clean the concurrent dictionary with nested locks
问题
我必须根据它们的键(UID)锁定对象,执行一些操作然后解锁。我想保持我的字典清晰。
因此,在这里我使用嵌套锁定。第一个是锁定整个字典,以安全地执行RemoveLock(uid)。第二个是锁定一个对象来执行操作。
我的问题是,在这个代码中我应该担心死锁吗?
英文:
I have to lock objects by their keys (UIDs), do some staff and unlock. And I want to keep my dictionary clear.
So here I use nested lock. The first is locking the whole dictionary just to safely perform RemoveLock(uid) at the end. And the second is locking an object to do stuff.
My question is should i fear deadlock in this code?
private static readonly ConcurrentDictionary<Guid, object> _lockDict = new ConcurrentDictionary<Guid, object>();
private static object _listLock;
public static void RunWithLock(Guid uid, Action body)
{
lock (_listLock)
{
var obj = GetLock(uid);
lock (obj)
{
body();
}
RemoveLock(uid);
}
}
public static void RemoveLock(Guid uid)
{
_lockDict.TryRemove(uid, out _);
}
public static object GetLock(Guid uid)
{
return _lockDict.GetOrAdd(uid, s => new object());
}
Tried to run it, didn't get any deadlocks. But thousands of objects processing every minute can make it deadlock.
答案1
得分: 1
没有,这段代码不会发生死锁。锁总是以相同的顺序获取,首先是 _listLock
,然后是字典中的一个对象,因此不会发生Dijkstra在他著名的哲学家就餐问题中描述的死锁条件。
但是,使用锁对象来保护 ConcurrentDictionary<K,V>
与使用 ConcurrentDictionary<K,V>
的初衷相违背。与使用普通的 Dictionary<K,V>
相比,你什么都没有,除了额外的开销和内存分配。此外,持有 _listLock
时调用 body
是糟糕的做法。这意味着所有 body
调用都会串行化,从而破坏了使用任何类型的字典,无论是并发的还是不并发的,的初衷。
英文:
> My question is should I fear deadlock in this code?
No, there is no risk of deadlock. The locks are always acquired in the same order, first the _listLock
and then one of the objects in the dictionary, so the deadlock condition that is described by Dijkstra in his famous Dining philosophers problem cannot occur.
That said, protecting a ConcurrentDictionary<K,V>
with a locker object defeats the purpose of using a ConcurrentDictionary<K,V>
in the first place. You get nothing compared to using a normal Dictionary<K,V>
, apart from extra overhead and memory allocations. Also calling the body
while holding the _listLock
is terrible. It means that all the body
invocations will be serialized, defeating the purpose of using any kind of dictionary, concurrent or not.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论