ReaderWriterLockSlim
一部の操作を保護するために使用しています。ライターよりもリーダーを優先したいと思います。これにより、リーダーがロックを長時間保持し、ライターが書き込みロックを取得しようとしているときに、その先のリーダーがライターの試みによってブロックされないようにすることができます (代わりに、ライターは でブロックされましたlock.EnterWriteLock()
)。
この目的のために、ライターがTryEnterWriteLock
ループ内で短いタイムアウトを使用できるので、後続のリーダーは引き続き読み取りロックを取得でき、ライターは取得できないと考えました。しかし、驚いたことに、 の呼び出しに失敗するとTryEnterWriteLock
、ロックの状態が変更され、今後のリーダーがブロックされることがわかりました。概念実証コード:
System.Threading.ReaderWriterLockSlim myLock = new System.Threading.ReaderWriterLockSlim(System.Threading.LockRecursionPolicy.NoRecursion);
System.Threading.Thread t1 = new System.Threading.Thread(() =>
{
Console.WriteLine("T1:{0}: entering read lock...", DateTime.Now);
myLock.EnterReadLock();
Console.WriteLine("T1:{0}: ...entered read lock.", DateTime.Now);
System.Threading.Thread.Sleep(10000);
});
System.Threading.Thread t2 = new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(1000);
while (true)
{
Console.WriteLine("T2:{0}: try-entering write lock...", DateTime.Now);
bool result = myLock.TryEnterWriteLock(TimeSpan.FromMilliseconds(1500));
Console.WriteLine("T2:{0}: ...try-entered write lock, result={1}.", DateTime.Now, result);
if (result)
{
// Got it!
break;
}
System.Threading.Thread.Yield();
}
System.Threading.Thread.Sleep(9000);
});
System.Threading.Thread t3 = new System.Threading.Thread(() =>
{
System.Threading.Thread.Sleep(2000);
Console.WriteLine("T3:{0}: entering read lock...", DateTime.Now);
myLock.EnterReadLock();
Console.WriteLine("T3:{0}: ...entered read lock!!!!!!!!!!!!!!!!!!!", DateTime.Now);
System.Threading.Thread.Sleep(8000);
});
このコードの出力は次のとおりです。
T1:18-09-2015 16:29:49: entering read lock...
T1:18-09-2015 16:29:49: ...entered read lock.
T2:18-09-2015 16:29:50: try-entering write lock...
T3:18-09-2015 16:29:51: entering read lock...
T2:18-09-2015 16:29:51: ...try-entered write lock, result=False.
T2:18-09-2015 16:29:51: try-entering write lock...
T2:18-09-2015 16:29:53: ...try-entered write lock, result=False.
T2:18-09-2015 16:29:53: try-entering write lock...
T2:18-09-2015 16:29:54: ...try-entered write lock, result=False.
T2:18-09-2015 16:29:54: try-entering write lock...
T2:18-09-2015 16:29:56: ...try-entered write lock, result=False.
T2:18-09-2015 16:29:56: try-entering write lock...
T2:18-09-2015 16:29:57: ...try-entered write lock, result=False.
T2:18-09-2015 16:29:57: try-entering write lock...
T2:18-09-2015 16:29:59: ...try-entered write lock, result=False.
T2:18-09-2015 16:29:59: try-entering write lock...
ご覧のとおり、スレッド 2 (「ライター」) はライター ロックを取得しておらず、EnterWriteLock
呼び出し中ではありませんが、スレッド 3 は完全にブロックされます。で同様の動作が見られReaderWriterLock
ます。
私は何か間違ったことをしていますか?そうでない場合、ライターがキューに入れられたときにリーダーを優先するために必要なオプションは何ですか?