Эрик Липперт и Нил Гафтер С# Головоломка
Эта головоломка была представлена в 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
- Вызывает исключение
- Ничего из вышеперечисленного
Ответы
Ответ 1
Я считаю, что проблема вызвана статичным иналитаризатором поля.
Я заметил, что новый поток запускается только тогда, когда выполняется doInitialize
(несмотря на то, что thread.Start()
вызывается) - , поэтому я полагаю, что CLR блокирует другие потоки, чтобы избежать параллельного доступа/двойной инициализации поля.
Подводя итог: недавно созданный поток не запускается CLR, чтобы избежать параллельного доступа, но основной поток инициализации ожидает выполнения дочернего потока, что означает тупик.
Edit
@Себастьян предложил (в комментарии) ссылку, которая может подтвердить мою теорию: http://blogs.msdn.com/b/pfxteam/archive/2011/05/03/10159682.aspx
Ответ 2
doInitialize
выполняется, когда статический тип сконструирован, а затем останавливается до тех пор, пока не завершится поток, который устанавливает PI
.
Тем не менее поток, который пытается установить PI
, не может быть запущен до тех пор, пока тип не будет инициализирован, что произойдет только после завершения инициализации (статический конструктор и статические инициализаторы) - что еще не произошло, как описано выше.
Таким образом, программные взаимоблокировки.
См. также этот ответ Эрика Липперта.
Ответ 3
Нить никогда не закончится, поэтому thread.Join() никогда не вернется.
doInitialize() выполняется из статического конструктора.
В статическом конструкторе мы пытаемся установить статическое свойство, но мы не можем получить доступ к статическому свойству, если статический конструктор не будет завершен.
гонки