Крестопроцессовая синхронизация чтения-записи, примитивная в .net?

StackOverflow https://stackoverflow.com/questions/3503833

Вопрос

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

Это было полезно?

Решение

Нет. Как отмечал Ричард выше, в .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.Ищите слова «Это решение неоптимальное» в статье выше.

Другие советы

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

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

Я создал этот класс на основе ответа Павла. Я еще не проверил его широко, но я создал простое приложение 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.");
    }
}

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

Вы смотрели на System.Threading.ReaderWriteLock? Вот MSDN Связь.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top