Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Eric Lippert和Neal Gafter C#Puzzle_C# - Fatal编程技术网

Eric Lippert和Neal Gafter C#Puzzle

Eric Lippert和Neal Gafter C#Puzzle,c#,C#,这个谜题是在2010年国家数据中心上提出的。那里有视频链接,但都断了。我不理解这个程序的行为;为什么要挂起来 class Woot { private static float PI; private static bool initialized = doInitialize(); private static bool doInitialize() { if (!initialized) { var t

这个谜题是在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
  • 抛出异常
  • 以上都没有

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

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

编辑


@Sebastian(在一篇评论中)提出了一个可以证明我的理论的链接:

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

但是,尝试设置
PI
的线程在初始化类型之前无法运行,这仅在初始化(静态构造函数和静态初始化器)完成后发生,而按照上面的说明还没有发生

所以程序死锁了


另请参见Eric Lippert的文章。

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

@Sayse,你的意思是当线程试图使用元数据类型对象时,它还没有被构造出来?这是我的猜测。@Yola-你可能想在问题的最后加上“我不理解程序的行为。它挂起了。”不要泄露游戏内容。:)@这是一个完全不同的问题。即使另一个问题的作者想问同一个问题——这个问题更清楚。@Sebastian这里的答案解释了这个问题。我在这篇博文中解释了发生的事情:。顺便说一句,这个谜题改编自Neal关于Java谜题的书中一个非常相似的谜题;Java在运行静态初始化时具有相同的行为。非常好,可能是正确的答案,需要一些证明链接。我认为这些是相关链接:-最后@Yola是的,我正在深入MSDN以找到证明。到目前为止,我发现的唯一一件事是声明,静态字段初始化是线程安全的,但没有声明如何确保线程安全。Eric Lippert有一篇博客文章详细说明了这个问题,这是非常容易误导的。如果在类型初始值设定项完成之前无法设置静态成员,则类型初始值设定项无法设置静态成员变量——显然为false。在静态构造函数完成之前,
PI
不会被设置,这一事实是这个特定程序中特殊的代码安排的结果,决不是一个通用语句。最好说“设置
PI
的代码无法运行…”