.NETのクロスプロセスREAD-WRITE同期プリミティブ?
-
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();
}
別の方法は次のとおりです。
上記のように、ロックを読む。次のようにロックを書き込む(pseudocode):
- 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には、クロスプロセスリーダーライターロックが含まれていません。セマフォとミューテックスの組み合わせを使用するために使用することができます(ミューテックスは、排他的アクセスのために作家または読者によって保持されます。これはセマフォを使用して他の読者を解放します。 。
ただし、競合が低いと予想される場合(つまり、スレッドがロックを長く保持していない)、相互排除はさらに速い場合があります。読者用ライターのロックの追加の複雑さは、複数の読者を許可することの利点を圧倒します(読者の文字)ロックは、より多くの読者とロックがかなりの時間保持されている場合にのみ高速になりますが、プロファイリングのみがこれを確認できます。)
Pavelの答えに基づいてこのクラスを作成しました。まだ広範囲にテストしていませんが、テストするための簡単な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 リンク。