Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 死锁检测有序锁的实现_C#_Locking_Deadlock - Fatal编程技术网

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。我不敢苟同。循环等待是死锁的常见原因。死锁无法轻松调试,因为在测试时无法经常重现,而且死锁会突然出现在生产环境中。