C# readerwriterlock是否允许在获取写锁时进行读取?
我有一个静态类,它由多个远程处理和应用程序线程的其他内部线程访问。这个类的部分功能是控制对各种文件的读/写访问,因此我在文件列表上实现了一个静态ReaderWriterLock。该项目使用.net framework 2.0作为客户需求的一部分 但是,当我使用多个不同的客户端(通常我使用16个)对系统进行压力测试时,每个客户端都会执行大量的读写操作,然后是非常间歇性的,只有在几个小时甚至几天之后,至少完成了500k+事务,系统才会崩溃。好的,我们有一个bug 但是,当我检查所有锁定事件的日志时,我可以看到发生了以下情况: 1:线程A直接获取写锁,检查IsWriterLock会显示为true 2:线程B尝试获取读卡器锁并且成功,即使线程a仍然具有写锁 3:系统现在崩溃,堆栈跟踪现在显示readerwriterlock的空引用异常 这个过程之前已经运行了几十万次,没有任何错误,我可以检查日志,看到在写退出之前,读锁在所有情况下都被阻塞。我还尝试将readerwriterlock作为一个单例实现,但问题仍然存在 以前有人见过这样的吗 所使用的readerwriterlock实现的精简版本如下所示:C# readerwriterlock是否允许在获取写锁时进行读取?,c#,multithreading,C#,Multithreading,我有一个静态类,它由多个远程处理和应用程序线程的其他内部线程访问。这个类的部分功能是控制对各种文件的读/写访问,因此我在文件列表上实现了一个静态ReaderWriterLock。该项目使用.net framework 2.0作为客户需求的一部分 但是,当我使用多个不同的客户端(通常我使用16个)对系统进行压力测试时,每个客户端都会执行大量的读写操作,然后是非常间歇性的,只有在几个小时甚至几天之后,至少完成了500k+事务,系统才会崩溃。好的,我们有一个bug 但是,当我检查所有锁定事件的日志时,
private const int readwriterlocktimeoutms = 5000;
private static ReaderWriterLock readerWriterLock = new ReaderWriterLock();
// this method will be called by thread A
public static void MethodA()
{
// bool to indicate that we have the lock
bool IsTaken = false;
try
{
// get the lock
readerWriterLock.AcquireWriterLock(readwriterlocktimeoutms);
// log that we have the lock for debug
// Logger.LogInfo("MethodA: acquired write lock; writer lock held {0}; reader lock held {1}", readerWriterLock.IsWriterLockHeld.ToString(),readerWriterLock.IsReaderLockHeld.ToString(), );
// mark that we have taken the lock
IsTaken = true;
}
catch(Exception e)
{
throw new Exception(string.Format("Error getting lock {0} {1}", e.Message, Environment.StackTrace));
}
try
{
// do some work
}
finally
{
if (IsTaken)
{
readerWriterLock.ReleaseWriterLock();
}
}
}
// this method will be called by thread B
public static void MethodB()
{
// bool to indicate that we have the lock
bool IsTaken = false;
try
{
// get the lock
readerWriterLock.AcquireReaderLock(readwriterlocktimeoutms);
// log that we have the lock for debug
// Logger.LogInfo("MethodB: acquired read lock; writer lock held {0}; reader lock held {1}", readerWriterLock.IsWriterLockHeld.ToString(),readerWriterLock.IsReaderLockHeld.ToString(), );
// mark that we have taken the lock
IsTaken = true;
}
catch (Exception e)
{
throw new Exception(string.Format("Error getting lock {0} {1}", e.Message, Environment.StackTrace));
}
try
{
// do some work
}
finally
{
if (IsTaken)
{
readerWriterLock.ReleaseReaderLock();
}
}
}
enter code here
如果是MSDN,则不可能同时保持读写器锁。
由于其他原因,在您的过程中是否可能在任何时候拥有2个readerWriterLock对象
另一件奇怪的事情是,使用iswriterlockhold调试线程,而当前线程是reader线程,不允许您了解在另一个线程中编写。
您如何知道线程A仍然持有写入程序锁,以及如何知道不是调试日志系统延迟或“混合”线程给出的指令
另一种想法是,其他资源共享是否可能导致死锁?那会导致崩溃吗?同时,空异常仍然是奇怪的,除非在哪里考虑死锁清除和READ RealWreBoice复位。
你的问题很奇怪,真的
还有一个问题,这并不能解决您的问题。您使用isTaken做什么,而在调试应用程序时,您依赖于ISWriterLockHold(或ISReaderLockHold)?
为什么不在finally block中使用它呢?@All终于找到了这个问题的解决方案。@Yannick您走对了方向 如果MSDN说不可能同时持有读写器锁 今天,我从微软得到确认,如果多处理器系统的负载非常重(注意:我永远不会在AMD系统上只在Intel上重现这个问题)ReaderWriterLock类对象可能会损坏,如果在任何给定阶段写入程序的数量增加,则这种情况的风险会增加,因为写入程序可以在队列中备份
在过去的两周里,我一直在使用.Net 3.5 ReaderWriterLockSlim类运行,但没有遇到此问题,这与Microsoft已确认的ReaderWriterLockSlim类没有与fat ReaderWriterLock类相同的损坏风险相对应。要完成此操作,是否可以添加IsTaken=true语句?我不知道它是否解释了问题,但代码显然是错误的;发布必须是first try/finally的一部分-否则实际工作代码中的任何异常都将导致锁无法释放。Marc-我不确定我是否同意你的说法。如果工作代码中抛出任何异常,那么必须始终在t之前调用finally方法应用程序或线程终止。因此应始终释放锁。@JohnV2020-根据您的代码,似乎您在try-finally之外“做了一些工作”,因为注释在try-finally之外。我假设您的意思是您在try块内做工作。正确-工作在try/finally块内执行