我使用multethreading bug。现在我看到由于某种原因锁定甚至一次都没有执行但是被锁定了。我有下一堂课:
public sealed class Foo
{
private readonly object _lock = new object();
private static ulong _inCnt = 0;
public void SomeMethod(ulong poo)
{
lock (_lock)
{
_inCnt++;
... [some code]
}
}
}
我暂停了VS中的所有线程,检查了所有线程,发现SomeMethod
中只有一个线程正在等待lock (_lock)
被释放(_inCnt = 0)
。
我恢复线程,等待一段时间,暂停线程并看到相同的图片,相同(且只有一个)线程仍在等待lock (_lock)
中的SomeMethod
并且_inCnt
为零!
但是如果锁定将会是一个或多个(_inCnt++
是lock (_lock)
之后的第一行,没有异常发生,我们不会中止线程)。如何将其锁定为零并锁定?
答案 0 :(得分:9)
如果您的所有假设都是正确的,并且您确实确定从未出现意外的线程中止,那么您必须考虑GC堆数据损坏。 System.Object中存储锁状态的字段相当容易受到攻击,它是对象中的第一个字段。因此,即使是在pinvoked本机代码中的适度缓冲区溢出也可能会覆盖该字段并使CLR认为锁定被保留。
然而,假设是不可饶恕的问题和无法回答的问题的母亲。最好检查它们,它实际上是可调试的。我假设32位代码执行。使用Debug + QuickWatch并键入&_lock
。这为您提供了对象引用的地址。切换到Debug + Windows + Memory + Memory1并输入您获得的地址。右键单击窗口并选择“4字节整数”。您现在将看到对象的地址,它存储在GC堆中。从该数字中减去4并在“地址”框中键入结果。您现在可以看到存储锁定状态的字段。如果未保持锁定为0,如果保持锁定,则它包含拥有锁定的线程的Thread.ManagedId。您可以将它与Debug + Windows + Threads窗口相关联。
三种基本情景: