同一个函数内多个异步锁
通常,使用异步锁都是直接使用这个库 AsyncEx 中的 AsyncLock
。
先看看官方栗子:
private readonly AsyncLock _mutex = new AsyncLock();
public async Task UseLockAsync()
{
// AsyncLock can be locked asynchronously
using (await _mutex.LockAsync())
{
// It's safe to await while the lock is held
await Task.Delay(TimeSpan.FromSeconds(10));
}
}
这个栗子的效果是如果有很多用户同时访问进来,里面的内容会 one by one 执行,不会出现同时执行的情况。
假设有这样一个情况, 里面的逻辑内容是针对某个用户的。
private readonly AsyncLock _mutex = new AsyncLock();
public async Task SomeFunAsync(string userId)
{
// AsyncLock can be locked asynchronously
using (await _mutex.LockAsync())
{
// It's safe to await while the lock is held
await Task.Delay(TimeSpan.FromSeconds(10));
// do something for user id.
}
}
希望里面的内容只针对同一个用户访问的时候,不允许同时操作。比如,对用户的余额操作。
解决方法是对不同的 user 创建不同的 AsyncLock
。
如下:
static readonly ConcurrentDictionary<string, Lazy<AsyncLock>> _mutexs = new ConcurrentDictionary<string, Lazy<AsyncLock>>();
public async Task SomeFunAsync(string userId)
{
var _mutex = _mutexs.GetOrAdd(userId, (_) => new Lazy<AsyncLock>(() => new AsyncLock())).Value;
// AsyncLock can be locked asynchronously
using (await _mutex.LockAsync())
{
// It's safe to await while the lock is held
await Task.Delay(TimeSpan.FromSeconds(10));
// do something for user id.
}
}
使用 ConcurrentDictionary<string, Lazy<AsyncLock>>
并发字典和懒加载来获取每个用户的 AsyncLock
。
Categories:
.net
已禁用评论。