用于多种方法配置的异步锁

本文关键字:异步 配置 方法 用于 | 更新日期: 2023-09-27 18:36:08

我需要实现的是:

  1. 当 MasterAsync 正在执行时,HumbleSlave1Async 和 HumbleSlave2Async 不能执行。
  2. 反之亦然 - 当一个或两个从属服务器正在执行时,主异步不能。
  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 时?

用于多种方法配置的异步锁

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

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

也就是说,你的方案适合读取器/写入器锁。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);
    }
}

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

也许你应该使用类似AsyncManualResetEvent的东西来做到这一点。

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

  1. _asyncLock1(或者您不会获得它HumbleSlave2Async
  2. _asyncLock2(或者您不会获得它HumbleSlave1Async

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