Eric Lippert和Neal Gafter C#拼图

Yol*_*ola 40 c#

这个难题在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 3.14
  • 0
  • 引发异常
  • 以上都不是

小智 29

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

总结一下:CLR不启动新创建的线程以避免并发访问,但主要的初始化线程等待子线程完成意味着死锁.

编辑

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

  • Eric Lippert有一个博客文章,详细说明了这个问题,[无锁死锁](http://ericlippert.com/2013/01/31/the-no-lock-deadlock/) (6认同)
  • 我认为这些是相关的链接:[Blog1](http://blogs.msdn.com/b/pfxteam/archive/2011/05/03/10159682.aspx) - [Blog2](http://blog.duncanworthy .me/swdev/csdotnet/constructor-gotchas-part3-deadlock /)最后[ECMAScript](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf#page= 178变焦=自动,87610" ) (3认同)

pok*_*oke 16

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

PI然而,尝试设置的线程在初始化类型之前无法运行,只有在初始化(静态构造函数和静态初始化器)完成后才会发生 - 这种情况在上面尚未发生.

所以该程序陷入僵局.

请参阅Eric Lippert的回答.