Крестопроцессовая синхронизация чтения-записи, примитивная в .net?
-
29-09-2019 - |
Вопрос
Существует ли механизм блокировки чтения/записи, который работает в процессах (аналогично 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 Связь.