gpt4 book ai didi

.net - 当作者试图进入写锁时如何避免阻塞 ReaderWriterLockSlim 读者

转载 作者:行者123 更新时间:2023-12-04 04:21:18 27 4
gpt4 key购买 nike

我正在使用 ReaderWriterLockSlim保护一些操作。我想偏爱读者而不是作者,这样当读者长时间持有锁并且作者试图获取写锁时,进一步的读者不会被作者的尝试阻塞(如果作者在 lock.EnterWriteLock() 上被阻止)。

为此,我认为作者可以使用 TryEnterWriteLock循环中的超时时间很短,这样后续的读者仍然能够获得读锁,而作者却不能。然而,令我惊讶的是,我发现对 TryEnterWriteLock 的调用不成功。更改锁的状态,无论如何都会阻止 future 的读者。概念验证代码:

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(“Writer”)尚未获得写入器锁并且它不在 EnterWriteLock 中。调用,线程 3 被永久阻塞。我可以看到与 ReaderWriterLock 类似的行为.

我做错什么了吗?如果不是,当作家排队时,我必须有哪些选择来支持读者?

最佳答案

我忍不住,但我相信这是一个 .NET Framework 错误(更新:我有 reported the bug)。以下简单的程序(上述程序的简化版本)说明了这一点:

var myLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);

var t1 = new Thread(() =>
{
Console.WriteLine("T1:{0}: entering read lock...", DateTime.Now);
myLock.EnterReadLock();
Console.WriteLine("T1:{0}: ...entered read lock.", DateTime.Now);

Thread.Sleep(50000);

Console.WriteLine("T1:{0}: exiting", DateTime.Now);
myLock.ExitReadLock();
});

var t2 = new Thread(() =>
{
Thread.Sleep(1000);

Console.WriteLine("T2:{0}: try-entering write lock...", DateTime.Now);
bool result = myLock.TryEnterWriteLock(3000);
Console.WriteLine("T2:{0}: ...try-entered write lock, result={1}.", DateTime.Now, result);

Thread.Sleep(50000);

if (result)
{
myLock.ExitWriteLock();
}
Console.WriteLine("T2:{0}: exiting", DateTime.Now);
});

var t3 = new Thread(() =>
{
Thread.Sleep(2000);

Console.WriteLine("T3:{0}: entering read lock...", DateTime.Now);
myLock.EnterReadLock();
Console.WriteLine("T3:{0}: ...entered read lock!!!!!!!!!!!!!!!!!!!", DateTime.Now);

Thread.Sleep(50000);

myLock.ExitReadLock();
Console.WriteLine("T3:{0}: exiting", DateTime.Now);
});

t1.Start();
t2.Start();
t3.Start();

t1.Join();
t2.Join();
t3.Join();

以下以简单的顺序发生,没有锁定车队,没有比赛,没有循环或任何事情。
  • T1获取读锁。
  • T2尝试获取写锁并阻塞,等待超时(因为 T1 持有锁)。
  • T3尝试获取读锁并阻塞(因为 T2 被阻塞等待写锁,并且根据文档,这意味着所有进一步的读取器都被阻塞,直到超时)。
  • T2的超时时间到期。根据文档,T3现在应该唤醒并获取读锁。然而,这并没有发生,T3被永久阻塞(或者,在本例中,在 T1 离开读锁之前的 50 秒内)。

  • AFAICT, ExitMyLock ReaderWriterLockSlim ’s WaitOnEvent 应该是 ExitAndWakeUpAppropriateWaiters .

    关于.net - 当作者试图进入写锁时如何避免阻塞 ReaderWriterLockSlim 读者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32654687/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com