4

我需要实现的是:

  1. 当 MasterAsync 正在执行时,HumbleSlave1Async 和 HumbleSlave2Async 不能。
  2. 反之亦然 - 当一个或两个从属设备正在执行时,MasterAsync 不能。
  3. 困难的部分-奴隶不能互相阻挡。

(链接到使用的AsyncLock)。

    private async Task MasterAsync()
    {
        using (await _asyncLock.LockAsync())
        {
            await Task.Delay(2000);
        }
    }
    private async Task HumbleSlave1Async()
    {
        using (await _asyncLock.LockAsync())
        {
            await Task.Delay(5000);
        }
    }
    private async Task HumbleSlave2Async()
    {
        using (await _asyncLock.LockAsync())
        {
            await Task.Delay(5000);
        }
    }

我不知道如何解决它,正在考虑为 MasterAsync 中的每个从站使用两个不同的锁,但是一个锁将在另一个锁中:

    private async Task MasterAsync()
    {
        using (await _asyncLock1.LockAsync())
        {
            using (await _asyncLock2.LockAsync())
            {
                await Task.Delay(2000);
            }
        }
    }
    private async Task HumbleSlave1Async()
    {
        using (await _asyncLock1.LockAsync())
        {
            await Task.Delay(5000);
        }
    }
    private async Task HumbleSlave2Async()
    {
        using (await _asyncLock2.LockAsync())
        {
            await Task.Delay(5000);
        }
    }

它是否有意义并且是否安全(死锁等),尤其是当我使用 AsyncLock 时?

4

3 回答 3

6

当 MasterAsync 正在执行时,HumbleSlave1Async 和 HumbleSlave2Async 不能。反之亦然 - 当一个或两个从属设备正在执行时,MasterAsync 不能。困难的部分-奴隶不能互相阻挡。

首先,仔细检查你是否真的想要这个。大多数时候,代码职责的重组将简化您需要的同步(通常也更有效)。

也就是说,您的场景适合读/写锁。RWL 是一种可以采用两种不同方式的锁,作为“写入者”(同时不允许任何其他锁)或作为“读取者”(允许其他读取者但不允许写入者)。Stephen Toub 在这里async有一个兼容的,我有一个作为我的AsyncEx 库的一部分。

更新:示例代码:

private readonly AsyncReaderWriterLock _lock = new AsyncReaderWriterLock();
private async Task MasterAsync()
{
    using (await _lock.WriterLockAsync())
    {
        await Task.Delay(2000);
    }
}
private async Task HumbleSlave1Async()
{
    using (await _lock.ReaderLockAsync())
    {
        await Task.Delay(5000);
    }
}
private async Task HumbleSlave2Async()
{
    using (await _lock.ReaderLockAsync())
    {
        await Task.Delay(5000);
    }
}
于 2013-10-21T14:11:20.230 回答
1

您的方法可能存在的问题是,当HumbleSlave2Async正在执行、MasterAsync已被调用、已获取asyncLock1和正在等待asyncLock2时,您将无法执行HumbleSlave1Async(因为asyncLock1被 占用MasterAsync)。因此,您的条件 #3 将不会得到满足。

也许您应该使用AsyncManualResetEvent 之类的东西来完成这项工作。

于 2013-10-21T12:04:55.933 回答
1

这当然不会死锁,因为您总是以相同的顺序获取锁:

  1. _asyncLock1(或者你没有获得它HumbleSlave2Async
  2. _asyncLock2(或者你没有获得它HumbleSlave1Async

全锁顺序保证了死锁的自由。

于 2013-10-21T13:39:59.187 回答