【问题标题】:Eric Lippert and Neal Gafter C# Puzzle [duplicate]Eric Lippert 和 Neal Gafter C# 拼图 [重复]
【发布时间】:2015-04-08 06:28:56
【问题描述】:

这个谜题是在 NDC 2010 上展示的。那里有视频链接,但它们都坏了。我不明白这个程序的行为;为什么会挂起?

class Woot
{
    private static float PI;
    private static bool initialized = doInitialize();

    private static bool doInitialize()
    {
        if (!initialized)
        {
            var thread = new Thread(() => { PI = 3.14f; });
            thread.Start();
            thread.Join(); // here
        }
        return true;
    }

    public static void Main(string[] args)
    {
        Console.WriteLine(PI);
    }
}

这个程序的输出是什么?是吗:

  • 3.14
  • 0
  • 抛出异常
  • 以上都不是

【问题讨论】:

  • @Sayse,你的意思是当线程试图使用元数据类型对象时还没有构造它?这是我的猜测。
  • @Yola - 你可能想把“而且我无法理解程序的行为。它挂起。”在结束你的问题是不要放弃游戏。 :)
  • @poke 那是一个完全不同的问题。即使另一个问题的作者打算问同样的问题 - 这个问题更清楚。
  • @Sebastian 那里的 answer 解释了这个问题。
  • 我在这篇博文中解释了发生了什么:ericlippert.com/2013/01/31/the-no-lock-deadlock。顺便说一句,这个谜题改编自尼尔关于 Java 谜题的书中的一个非常相似的谜题。 Java 在运行静态初始化时具有相同的行为。

标签: c#


【解决方案1】:

我认为问题是由静态字段初始化器引起的。 我发现新线程只有在 doInitialize 完成后才会启动(尽管调用了 thread.Start()) - 所以我认为 CLR 会阻止其他线程以避免并发访问/双字段初始化

总结:新创建的线程不是由CLR启动以避免并发访问,而是主初始化线程等待子线程完成,这意味着死锁

编辑

@Sebastian 提出(在评论中)可以证明我的理论的链接:http://blogs.msdn.com/b/pfxteam/archive/2011/05/03/10159682.aspx

【讨论】:

  • 很好,可能是正确答案,需要一些证明链接。
  • 我认为这些是相关链接:Blog1 - Blog2 最后是ECMAScript
  • @Yola 是的,我正在挖掘 MSDN 以寻找证明。到目前为止,我发现的唯一内容是声明,静态字段初始化是线程安全的,但没有声明如何确保线程安全。
  • Eric Lippert 有一篇博文详细说明了这个问题,The no-lock deadlock
【解决方案2】:

doInitialize在构造静态类型时执行,然后暂停,直到设置PI的线程终止。

尝试设置 PI 的线程在类型初始化之前无法运行,这仅在初始化(静态构造函数和静态初始化程序)完成后才会发生 - 如上所述尚未发生。

所以程序死锁了。

另请参阅 Eric Lippert 的 this answer

【讨论】:

  • 这是高度误导。如果在类型初始化程序完成之前无法设置静态成员,则类型初始化程序无法设置静态成员变量——显然是错误的。 PI 直到静态构造函数完成后才会被设置的事实是这个特定程序中特殊代码排列的结果,绝不是通用语句。最好说“设置PI 的代码无法运行...”
【解决方案3】:

线程永远不会结束,所以 thread.Join() 永远不会返回。 doInitialize() 从静态构造函数执行。 在静态构造函数中,我们试图设置静态属性,但除非静态构造函数完成,否则我们无法访问静态属性。 种族

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多