Кросс-процессная синхронизация чтения-записи в .NET? - PullRequest
6 голосов
/ 17 августа 2010

Существует ли механизм блокировки чтения / записи, который работает в разных процессах (аналогично Mutex, но вместо эксклюзивной блокировки чтения / записи)? Я хотел бы разрешить одновременный доступ на чтение, но эксклюзивный доступ на запись.

Ответы [ 5 ]

5 голосов
/ 26 февраля 2013

Нет. Как заметил выше Ричард, в .NET такого механизма нет. Вот как это реализовать, используя мьютекс и семафор.

Метод # 1 описан в http://www.joecheng.com/blog/entries/Writinganinter-processRea.html,, цитата:

// create or open global mutex
GlobalMutex mutex = new GlobalMutex("IdOfProtectedResource.Mutex");
// create or open global semaphore
int MoreThanMaxNumberOfReadersEver = 100;

GlobalSemaphore semaphore = new GlobalSemaphore("IdOfProtectedResource.Semaphore", MoreThanMaxNumberOfReadersEver);

public void AcquireReadLock()
{
  mutex.Acquire();
  semaphore.Acquire();
  mutex.Release();
}

public void ReleaseReadLock()
{
  semaphore.Release();
}

public void AcquireWriteLock()
{
  mutex.Acquire();
  for (int i = 0; i < MoreThanMaxNumberOfReadersEver; i++)
    semaphore.Acquire(); // drain out all readers-in-progress
  mutex.Release();
}

public void ReleaseWriteLock()
{
  for (int i = 0; i < MoreThanMaxNumberOfReadersEver; i++)
    semaphore.Release();
}

Альтернативой будет:

Чтение блокировки - как указано выше. Запишите блокировку следующим образом (псевдокод):

- Lock mutex
- Busy loop until the samaphore is not taken AT ALL:
-- wait, release.
-- Release returns value; 
-- if value N-1 then break loop.
-- yield (give up CPU cycle) by using Sleep(1) or alternative
- Do write
- Release mutex

Следует отметить, что возможен более эффективный подход, как здесь: http://en.wikipedia.org/wiki/Readers-writers_problem#The_second_readers-writers_problem Ищите слова «Это решение неоптимально» в статье выше.

5 голосов
/ 17 августа 2010

Windows не включает межпроцессную блокировку Reader-Writer.Комбинация семафоров и мьютексов может использоваться для их создания (мьютекс удерживается автором для эксклюзивного доступа или читателем, который затем использует семафор для освобождения других читателей, т. Е. Писатели будут ждать только мьютекса и читателей для любого из них).

Однако, если ожидается, что конкуренция будет низкой (т. Е. Ни один поток не удерживает блокировку в течение длительного времени), взаимное исключение может все же быть быстрее: дополнительная сложность блокировки чтения-записи подавляет любые преимущества, связанные с разрешением нескольких читателей.в. (Блокировка чтения-записи будет быстрее, только если будет гораздо больше считывателей, а блокировки удерживаются в течение значительного времени, но это может подтвердить только ваше профилирование.)

0 голосов
/ 15 декабря 2018

Я создал этот класс на основе ответа Павла.Я еще не тестировал его всесторонне, но я создал простое приложение winforms, чтобы протестировать его, и пока оно хорошо работает.

Обратите внимание, что он использует семафор, поэтому он не поддерживает повторный вход.

public class CrossProcessReaderWriterLock
{
    private readonly string _name;
    const int _maxReaders = 10;

    readonly Mutex     _mutex;
    readonly Semaphore _semaphore;

    public CrossProcessReaderWriterLock(string name)
    {
        _name = name;
        _mutex     = new Mutex(false, name + ".Mutex");
        _semaphore = new Semaphore(_maxReaders, _maxReaders, name + ".Semaphore");
    }

    public void AcquireReaderLock()
    {
        //Log.Info($"{_name} acquiring reader lock...");

        _mutex    .WaitOne();
        _semaphore.WaitOne();
        _mutex    .ReleaseMutex();

        //Log.Info($"{_name} reader lock acquired.");
    }

    public void ReleaseReaderLock()
    {
        _semaphore.Release();

        //Log.Info($"{_name} reader lock released.");
    }

    public void AcquireWriterLock()
    {
        //Log.Info($"{_name} acquiring writer lock...");

        _mutex.WaitOne();

        for (int i = 0; i < _maxReaders; i++)
            _semaphore.WaitOne(); // drain out all readers-in-progress

        _mutex.ReleaseMutex();

        //Log.Info($"{_name} writer lock acquired.");
    }

    public void ReleaseWriterLock()
    {
        for (int i = 0; i < _maxReaders; i++)
            _semaphore.Release();

        //Log.Info($"{_name} writer lock released.");
    }
}
0 голосов
/ 17 августа 2010

Вы смотрели на System.Threading.ReaderWriteLock? Вот ссылка MSDN .

0 голосов
/ 17 августа 2010

System.Threading.Mutex имеет мьютекс, который можно использовать для внутрипроцессного взаимодействия. Если вам нужна функциональность, которую он не поддерживает, ее можно реализовать через мьютекс.

...