我如何锁定一个整数与异步调用里面?



目前我使用这个类(从这里得到它):

public static class IntSynchronizer
{
private static readonly ConcurrentDictionary<int, object> locks;
static IntSynchronizer()
{
locks = new ConcurrentDictionary<int, object>();
}
public static object GetLock(int id)
{
return locks.GetOrAdd(id, new object());
}
}

然后我用

lock (IntSynchronizer.GetLock(clientId))
{
// do stuff (nothing async) that can only be done once per client at any given moment
}

这是有效的,但显然你不能使用这个,如果你需要进行异步调用。

然后我找到了另一种方法,像这样:

private static readonly SemaphoreSlim _someLock = new (1,1);

然后像这样使用

await _someLock.WaitAsync();
try
{
// do async things that can only be done one at a time
}
finally
{
_someLock.Release();
}

我需要把这些东西结合起来。我如何像第一个例子那样锁定一个整数,但支持异步调用,像第二个例子一样?

public static class AsyncIntSynchronizer
{
private static readonly ConcurrentDictionary<int, SemaphoreSlim> _semaphores = new();
public static ValueTask<DisposableRelease> GetAsyncLock(int id)
{
return _semaphores
.GetOrAdd(id, new SemaphoreSlim(1, 1))
.WaitAsyncScoped();
}
}
public static class SemaphoreSlimExtensions
{
public static async ValueTask<DisposableRelease> WaitAsyncScoped(this SemaphoreSlim @this)
{
await @this.WaitAsync();
return new DisposableRelease(@this);
}
}
public struct DisposableRelease : IDisposable
{
private readonly SemaphoreSlim _semaphoreSlim;
public DisposableRelease(SemaphoreSlim semaphoreSlim) => _semaphoreSlim = semaphoreSlim;
public void Dispose() => _semaphoreSlim.Release();
}
class TestClass
{
private async Task Main()
{
using (await AsyncIntSynchronizer.GetAsyncLock(1))
{
}
}
}

还请记住,来自同一线程的连续锁是可以接受的(计数为1),但是来自同一线程计数的对WaitAsync的连续调用彼此独立

最新更新