gpt4 book ai didi

c# - 如何保护可能在多线程或异步环境中使用的资源?

转载 作者:可可西里 更新时间:2023-11-01 08:03:10 24 4
gpt4 key购买 nike

我正在开发供各种消费者使用的 C# API。此 API 提供对共享资源的访问(在我的例子中是进行串行通信的硬件),通常会有几个不同的参与者试图同时使用它。

我遇到的问题是我的一些消费者会想在多线程环境中使用它——每个参与者独立工作并尝试使用该资源。一个简单的锁在这里工作得很好。但是我的一些消费者更喜欢使用异步等待和时间片资源。 (据我了解)这需要一个异步锁来将时间片返回给其他任务;锁定锁会停止整个线程。

而且我认为拥有串行锁充其量是性能不佳的,最坏的情况是潜在的竞争条件或死锁。

那么我如何才能在公共(public)代码库中为这两种潜在的并发使用保护这个共享资源呢?

最佳答案

您可以使用 SemaphoreSlim请求数为 1。 SemaphoreSlim 允许使用 WaitAsyncasync 方式锁定和旧的同步方式:

await _semphore.WaitAsync()
try
{
... use shared resource.
}
finally
{
_semphore.Release()
}

您还可以根据 Stephen Toub 的精彩帖子 Building Async Coordination Primitives, Part 6: AsyncLock 编写自己的 AsyncLock .我在我的应用程序中做到了这一点,并允许在同一构造上同时使用同步和异步锁。

用法:

// Async
using (await _asyncLock.LockAsync())
{
... use shared resource.
}

// Synchronous
using (_asyncLock.Lock())
{
... use shared resource.
}

实现:

class AsyncLock
{
private readonly Task<IDisposable> _releaserTask;
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
private readonly IDisposable _releaser;

public AsyncLock()
{
_releaser = new Releaser(_semaphore);
_releaserTask = Task.FromResult(_releaser);
}
public IDisposable Lock()
{
_semaphore.Wait();
return _releaser;
}
public Task<IDisposable> LockAsync()
{
var waitTask = _semaphore.WaitAsync();
return waitTask.IsCompleted
? _releaserTask
: waitTask.ContinueWith(
(_, releaser) => (IDisposable) releaser,
_releaser,
CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously,
TaskScheduler.Default);
}
private class Releaser : IDisposable
{
private readonly SemaphoreSlim _semaphore;
public Releaser(SemaphoreSlim semaphore)
{
_semaphore = semaphore;
}
public void Dispose()
{
_semaphore.Release();
}
}
}

关于c# - 如何保护可能在多线程或异步环境中使用的资源?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21011179/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com