AsyncDuplicateLock, который может быть заблокирован на всех ключах - PullRequest
3 голосов
/ 21 марта 2019

Мне нужен замок, похожий на тот, что приведен в ответе Стивена Клири: https://stackoverflow.com/a/31194647/4381408

Однако мне также нужно иметь возможность заблокировать все ключи одновременно.Я также использую библиотеку AsyncEx Стивена Клири , поэтому я подумал объединить AsyncDuplicateLock с AsyncReaderWriterLock следующим образом:

public sealed class AsyncDuplicateReaderWriterLock
{
    private AsyncReaderWriterLock _rwLock = new AsyncReaderWriterLock();
    private AsyncDuplicateLock _duplicateLock = new AsyncDuplicateLock();

    public IDisposable ReaderLock(object key)
    {
        return CollectionDisposable.Create(
                _rwLock.ReaderLock(),
                _duplicateLock.Lock(key)
            );
    }

    public async Task<IDisposable> ReaderLockAsync(object key)
    {
        return CollectionDisposable.Create(
            await _rwLock.ReaderLockAsync(),
            await _duplicateLock.LockAsync(key));
    }

    public IDisposable WriterLock()
    {
        return _rwLock.WriterLock();
    }

    public async Task<IDisposable> WriterLockAsync()
    {
        return await _rwLock.WriterLockAsync();
    }
}

Таким образом, я могу использовать ReaderLock для блокировки наключ и WriterLock для блокировки на все ключи.Крайне важно, чтобы я понял это правильно, поэтому я хочу быть уверен, что для этого нет возможности заблокировать или не заблокировать должным образом.Я не чувствую себя достаточно уверенно в этом.

Так что, будет ли эта работа несколько эффективна и безопасна для потоков?

Спасибо за помощь!

1 Ответ

2 голосов
/ 23 марта 2019

Я настоятельно, настоятельно советую вам сделать шаг назад, подумать о реальной проблеме, которую вы пытаетесь решить, объяснить ее кому-то еще и спросить их, как они решат проблемы параллелизма.

Тем не менее, да, вы можете (ab) использовать блокировку чтения / записи для этого. Лично я бы выделил блокировку:

public IDisposable ReaderLock(object key)
{
  var rwKey = _rwLock.ReaderLock();
  var duplicateKey = _duplicateLock.Lock(key);
  return CollectionDisposable.Create(rwKey, duplicateKey);
}

// (and the same for async)

Это делает более очевидным, что код сначала берет RWL (что он должен сделать, чтобы быть корректным).

...