我有一个看似非常简单的情况,其中我在3.5版本的.NET Framework中使用System.Threading.ReaderWriterLockSlim。我首先声明一个,如下所示:

Lock Declaration http://odeh.temp.s3.amazonaws.com/lock_declaration.bmp

我在获取锁之前就设置了一个断点,并进行了屏幕截图,以便您可以看到(在监视窗口中)当前没有持有锁:

pre lock acquisition http://odeh.temp.s3.amazonaws.com/prelock.bmp

然后,在调用EnterWriteLock之后,您将看到我持有一个读锁。

post lock acquisition http://odeh.temp.s3.amazonaws.com/postlock.bmp

这似乎是真正的意外行为,我在任何地方都找不到它的记录。有谁知道为什么会这样吗?在我的代码的其他位置(较早),此完全相同的代码行正确地获得了写锁定。但是,在多个系统中,一致地,它而是在调用堆栈中的此位置获得读取锁定。希望我已经阐明了这一点,并感谢您抽出宝贵的时间对此进行研究。

- - 编辑 - -

对于那些提到断言的人……这进一步使我感到困惑:

post assert http://odeh.temp.s3.amazonaws.com/assert.bmp

我真的不能说它是如何通过这个断言的,除了“监视窗口”和“即时窗口”可能是错误的(也许值存储在本地线程,如另一幅海报所述)之外。对于 volatile 变量和“先发生”关系而言,这似乎是显而易见的情况。无论哪种方式,稍后几行都有针对写锁定声明的代码,但没有一个。我在释放该锁的整个程序的唯一一行代码上设置了一个断点,并且在显示如下所示的获取之后它不会被调用,因此这必须意味着它从未真正被获取过……对吗?

最佳答案

这可能是调试器的副作用。 ReaderWriterLockSlim类对当前线程ID(Thread.ManagedThreadId)非常敏感。我无法说明调试器将始终使用当前事件线程来评估监视表达式的事实。它通常可以,但是如果您进入调试器时遇到困难,则可能会有不同的行为。

首先,请相信代码的作用,您的Debug.Assert证明了这一点。

10-06 10:41