使用异步方法在锁定中的最佳实践是什么?

5
在 .Net Core 中,许多 I/O 方法都有异步版本,并且微软建议我们使用它们以获得更好的性能。
但是众所周知,异步方法无法在普通锁中正常工作,因为普通锁与线程相关。
例如,在 MemoryCache 中使用 ReadWriteLocker。当 MemoryCache 缺失时,我需要从数据库读取数据。 目前我知道解决此问题的两种方式:
1. 将异步数据库查询方法转换为同步方法,例如“Wait”或“.Result”。 2. 使用特殊锁,如 Redis 锁或一些非官方的 AsyncReaderWriteLocker。(我已经找到了其中一个,但我还没有阅读过其代码,因此我不知道详情、成本或新 bug)
那么回到标题,当我必须在锁中使用异步方法时,什么是最好的方式?我需要一些建议。 非常感谢阅读我的糟糕英语。

4
您可以使用 SemaphoreSlim 类,该类具有 WaitAsync 方法。 - canton7
我知道如何使用SemaphoreSlim而不是简单锁,但是相比之下使用ReadWriteLocker会更困难。 - sybil
是的,不幸的是没有内置的异步读/写锁。 - canton7
我们一直非常成功地使用了Stephen Cleary的AsyncEx库中的AsyncReaderWriterLock - Matthew Watson
谢谢您的回答,我会阅读AsyncReaderWriteLocker的代码。但我想知道是否有更好的方法来解决这个问题。 - sybil
@MatthewWatson 非常感谢。我会研究这段代码的。 - sybil
1个回答

4

lock只是一个语法糖,用于监视器,它一次只允许一个线程进入,因此无法与async/await一起使用。

另一方面,Semaphore可以安全地协调多个线程对共享资源的访问。您可以使用SemaphoreSlim来完成所需的操作,就像这样。首先,在可从任何需要线程保护的地方访问的字段或属性中声明一个信号量:

public readonly SemaphoreSlim _mySemaphoreSlim = new SemaphoreSlim(1, 1);

然后像这样使用它:
await _mySemaphoreSlim.WaitAsync(cancellationToken);
// Do whatever other sync or async operations you need.
_mySemaphoreSlim.Release();

谢谢您的回答,我已经了解了SemaphoreSlim的基本用法,但是当我需要一个ReadWriteLocker时,使用SemaphoreSlim编写AsyncReadWriteLocker很困难。因此,我想知道是否有更好的方法来解决这个问题。 - sybil
5
你有关于它是语法糖信号量的任何文档吗?据我所知,它实际上是用于“Monitor”类的语法糖,该类使用为锁管理分配给所有引用类型的额外内存。 - user10608418

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接