我有一个静态类,可以通过多个远程访问和应用程序线程的其他内部访问.该类的部分功能是控制对各种文件的读/写访问,因此我在文件列表上实现了静态ReaderWriterLock.该项目使用.net framework 2.0作为客户需求的一部分.
然而,当我使用许多不同的客户端(通常我使用16个)对系统进行压力测试时,每个客户端都执行大量的读写操作,然后非常间歇性地执行,并且仅在几小时甚至几天之后才完成至少500k +交易完成了系统崩溃.好的,我们有一个bug ..
但是当我检查所有锁定事件的日志时,我可以看到发生了以下情况:
1:线程A直接获取写锁,检查IsWriterLock是否为真.
2:即使线程A仍然具有写锁定,线程B 也会尝试获取读取器锁定并成功
3:系统现在崩溃,堆栈跟踪现在显示readerwriterlock的空引用异常
此过程之前已运行了数十万次,没有任何错误,我可以检查日志,看到读取锁在之前的所有情况下都被阻止,直到写入退出.我也尝试将readerwriterlock实现为单例,但问题仍然存在
有没有人见过这样的事情?
使用的readerwriterlock实现的简化版本如下所示:
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
Run Code Online (Sandbox Code Playgroud)
@All终于有了解决这个问题的方法.@Yannick,你走在正确的轨道上......
如果MSDN说不可能同时保持读写器锁定.
今天我得到了微软的确认,在多处理器系统负载很重的情况下(注意:我永远不能在AMD系统上只在英特尔上重现这个问题),这可能会导致ReaderWriterLock类对象被破坏,如果这种情况有可能增加任何给定阶段的作者数量都会增长,因为这些可以在队列中备份.
在过去的两周里,我一直在使用.Net 3.5 ReaderWriterLockSlim类运行并且没有遇到过这个问题,这与微软已经确认readerwriterlockslim类没有胖胖的ReaderWriterLock类具有相同的破坏风险相对应.