C# 死锁检测有序锁的实现
我试图实现一种机制,在这种机制中,锁的顺序会自动检查,当锁在运行时无序获取时会抛出异常,以避免死锁。下面是一个参考实现。如果您发现此实现存在任何问题,请告诉我。非常感谢C# 死锁检测有序锁的实现,c#,locking,deadlock,C#,Locking,Deadlock,我试图实现一种机制,在这种机制中,锁的顺序会自动检查,当锁在运行时无序获取时会抛出异常,以避免死锁。下面是一个参考实现。如果您发现此实现存在任何问题,请告诉我。非常感谢 public class someResource { private OrderedLock lock1 = new OrderedLock(1); private OrderedLock lock2 = new OrderedLock(2); public void lockInOrder()
public class someResource
{
private OrderedLock lock1 = new OrderedLock(1);
private OrderedLock lock2 = new OrderedLock(2);
public void lockInOrder()
{
lock1.AcquireWriteLock();
lock2.AcquireWriteLock();
// do something
lock1.ReleaseWriteLock();
lock2.ReleaseWriteLock();
}
public void lockOutOfOrder()
{
lock2.AcquireReadLock();
lock1.AcquireReadLock(); // throws exception
// read something
lock2.ReleaseReadLock();
lock1.ReleaseReadLock();
}
}
public class OrderedLock : IDisposable
{
private static readonly ConcurrentDictionary<int, object> createdLocks = new ConcurrentDictionary<int, object>();
[ThreadStatic]
private static ISet<int> acquiredLocks;
private readonly ThreadLocal<int> refCount = new ThreadLocal<int>(false);
private readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private readonly int id;
/// <exception cref="InvalidOperationException">Duplicate identifier detected</exception>
public OrderedLock(int id)
{
if (!createdLocks.TryAdd(id, null))
{
throw new InvalidOperationException("Duplicate identifier detected");
}
this.id = id;
this.refCount.Value = 0;
}
public void AcquireReadLock()
{
this.CheckLockOrder();
this.locker.EnterReadLock();
}
public void AcquireWriteLock()
{
this.CheckLockOrder();
this.locker.EnterWriteLock();
}
public void ReleaseReadLock()
{
this.refCount.Value--;
this.locker.ExitReadLock();
if (this.refCount.Value == 0)
{
acquiredLocks.Remove(this.id);
}
}
public void ReleaseWriteLock()
{
this.refCount.Value--;
this.locker.ExitWriteLock();
if (this.refCount.Value == 0)
{
acquiredLocks.Remove(this.id);
}
}
public void Dispose()
{
while (this.locker.IsWriteLockHeld)
{
this.ReleaseWriteLock();
}
while (this.locker.IsReadLockHeld)
{
ReleaseReadLock();
}
this.locker.Dispose();
this.refCount.Dispose();
GC.SuppressFinalize(this);
}
/// <exception cref="InvalidOperationException">Invalid order of locking detected</exception>
private void CheckLockOrder()
{
if (acquiredLocks == null)
{
acquiredLocks = new HashSet<int>();
}
if (!acquiredLocks.Contains(this.id))
{
if (acquiredLocks.Any() && acquiredLocks.Max() > this.id)
{
throw new InvalidOperationException("Invalid order of locking detected");
}
acquiredLocks.Add(this.id);
}
this.refCount.Value++;
}
}
公共类资源
{
private OrderedLock lock1=新OrderedLock(1);
private OrderedLock lock2=新OrderedLock(2);
公共无效锁序()
{
lock1.AcquireWriteLock();
lock2.AcquireWriteLock();
//做点什么
lock1.ReleaseWriteLock();
lock2.ReleaseWriteLock();
}
公共无效锁序()
{
lock2.eadlock();
lock1.AcquisiteAdLock();//引发异常
//读点东西
锁2.释放ReadLock();
锁1.释放ReadLock();
}
}
公共类OrderedLock:IDisposable
{
私有静态只读ConcurrentDictionary createdLocks=new ConcurrentDictionary();
[线程静态]
私有静态ISet获取锁;
private readonly ThreadLocal refCount=new ThreadLocal(false);
private ReaderWriterLockSlim locker=new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
私有只读int-id;
///检测到重复的标识符
public OrderedLock(int-id)
{
如果(!createdLocks.TryAdd(id,null))
{
抛出新的InvalidOperationException(“检测到重复标识符”);
}
this.id=id;
this.refCount.Value=0;
}
公共密码锁()
{
这是CheckLockOrder();
this.locker.EnterReadLock();
}
公共无效AcquireWriteLock()
{
这是CheckLockOrder();
this.locker.EnterWriteLock();
}
public void ReleaseReadLock()
{
this.refCount.Value--;
this.locker.exitradlock();
如果(this.refCount.Value==0)
{
acquiredLocks.Remove(此.id);
}
}
public void ReleaseWriteLock()
{
this.refCount.Value--;
this.locker.ExitWriteLock();
如果(this.refCount.Value==0)
{
acquiredLocks.Remove(此.id);
}
}
公共空间处置()
{
while(this.locker.isWriteLockHold)
{
这是。ReleaseWriteLock();
}
而(此.locker.isReadLockHold)
{
释放ReadLock();
}
this.locker.Dispose();
this.refCount.Dispose();
总干事(本);
}
///检测到无效的锁定顺序
私人作废支票锁订单()
{
如果(acquiredLocks==null)
{
acquiredLocks=新哈希集();
}
如果(!acquiredLocks.Contains(this.id))
{
if(acquiredLocks.Any()&&acquiredLocks.Max()>this.id)
{
抛出新的InvalidOperationException(“检测到无效的锁定顺序”);
}
acquiredLocks.Add(this.id);
}
this.refCount.Value++;
}
}
无法同步访问您的mAcquiredLocks
。如果两个线程同时添加/删除锁,这将失败。谢谢Jim。但是每个线程都是静态的,每个线程应该创建一个不同的实例。我怎么会错过这个呢?你可能会在codereview上得到更好的响应。这段代码没有通过达尔文测试:如果它真的那么有用,那么为什么它还没有成为.NET框架的一部分呢?因为它只捕获死锁的小情况,那些已经很容易调试的情况。“出于琐碎的原因添加共享状态从来都不是一个好主意。@Hans。我不敢苟同。循环等待是死锁的常见原因。死锁无法轻松调试,因为在测试时无法经常重现,而且死锁会突然出现在生产环境中。