gpt4 book ai didi

c# - 损坏的锁?魔术僵局?

转载 作者:太空狗 更新时间:2023-10-29 22:32:35 26 4
gpt4 key购买 nike

我在处理多线程错误。现在我看到由于某种原因 lock 甚至没有执行一次而是被锁定了。我有下一节课:

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)。我恢复了线程,等了一会儿,暂停了线程,看到了同样的画面,同样的(而且只有一个)线程还在等待SomeMethod中的lock(_lock) _inCnt 为零!但如果锁将被输入,它将是一个或多个(_inCnt++lock (_lock) 之后的第一行,不会发生异常,我们不会中止线程) .怎么可能为零,锁上锁呢?

最佳答案

如果您的所有假设都是正确的,并且您确实确定不会发生意外线程中止,那么您必须考虑 GC 堆数据损坏。 System.Object 中存储锁定状态的字段非常容易受到攻击,它是对象中的第一个字段。因此,即使是在 pinvoked native 代码中适度的缓冲区溢出也可能会覆盖该字段并使 CLR 认为锁已被持有。

然而,假设是无法调试的问题和无法回答的问题之母。最好检查一下,它实际上是可以调试的。我假设执行 32 位代码。使用 Debug + QuickWatch 并键入 &_lock。这为您提供了对象引用的地址。切换到 Debug + Windows + Memory + Memory1 并键入您获得的地址。右键单击窗口并选择“4 字节整数”。您现在将看到对象的地址,它存储在 GC 堆中的位置。从该数字中减去 4,然后在“地址”框中键入结果。您现在可以看到存储锁定状态的字段。如果未持有锁,则为 0,如果持有,则它包含拥有该锁的线程的 Thread.ManagedId。您可以将其关联到“调试 + Windows + 线程”窗口。

三个基本场景:

  • 如果您在“线程”窗口中找到该线程,那么您就遇到了死锁,您将对该线程正在做什么非常感兴趣。双击它并查看“调用堆栈”窗口以了解它没有取得进展的原因
  • 如果你找不到那个线程,那么你有一个非常强烈的暗示,表明你的代码正在遭受“意外线程中止”事故的困扰
  • 如果您看到一个奇怪的随机数,那么您遇到了 GC 堆损坏情况。

关于c# - 损坏的锁?魔术僵局?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20345517/

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