如何保护可在一个多线程或异步环境中使用资源? [英] How to protect resources that may be used in a multi-threaded or async environment?

查看:98
本文介绍了如何保护可在一个多线程或异步环境中使用资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作所使用的各种消费者的C#API。这个API可以访问共享资源(在做串行通讯我的情况的硬件),这往往会产生一些不同的角色尝试同时使用它。

I am working on a C# API that is used by a variety of consumers. This API provides access to a shared resource (in my case hardware that does serial communication) , that will often have a few different actors trying to use it concurrently.

我的问题是,我的一些消费者会希望在多线程环境中使用此 - 每一个演员都独立工作并尝试使用该资源。一个简单的锁在这里工作得很好。但我的一些消费者将preFER使用异步的await和时间片资源。 (据我所知),这需要一个异步锁产生的时间片返回到其他任务;在锁定阻止将停止这整个主题。

The issue I have is that some of my consumers will want to use this in a multi-threaded environment - each actor works independently and try to use the resource. A simple lock works fine here. But some of my consumers would prefer to use async-await and time-slice the resource. (As I understand it) this requires an asynchronous lock to yield the timeslice back to other tasks; blocking at a lock would halt that whole thread.

和我想象有串行锁充其量unperformant,以及潜在的竞争条件或死锁在最坏的情况。

And I imagine that having serial locks is unperformant at best, and a potential race condition or deadlock at worst.

那么,如何保护这种共享资源在一个共同的codeBase的两个潜在的并发用法?

So how can I protect this shared resource in a common codebase for both potential concurrency usages?

推荐答案

您可以使用<一个href=\"http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim%28v=vs.110%29.aspx\"><$c$c>SemaphoreSlim用1作为请求的数目。 SemaphoreSlim 允许使用<一中既有异步时尚锁定href=\"http://msdn.microsoft.com/en-us/library/system.threading.semaphoreslim.waitasync%28v=vs.110%29.aspx\"><$c$c>WaitAsync和旧的同步方式:

You can use SemaphoreSlim with 1 as the number of requests. SemaphoreSlim allows to lock in both an async fashion using WaitAsync and the old synchronous way:

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

您也可以编写自己的基于斯蒂芬Toub的伟大后的 AsyncLock 2012/02/12 / 10266988.aspx>建筑异步协调原语,第6部分:AsyncLock 。我做到了我的应用程序,并允许对同一构造同步和异步锁。

You can also write your own AsyncLock based on Stephen Toub's great post Building Async Coordination Primitives, Part 6: AsyncLock. I did it in my application and allowed for both synchronous and asynchronous locks on the same construct.

用法:

// 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();
        }
    }
}

这篇关于如何保护可在一个多线程或异步环境中使用资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆