{"id":56053,"date":"2011-05-03T03:05:00","date_gmt":"2011-05-03T03:05:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/pfxteam\/2011\/05\/03\/static-constructor-deadlocks\/"},"modified":"2011-05-03T03:05:00","modified_gmt":"2011-05-03T03:05:00","slug":"static-constructor-deadlocks","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/static-constructor-deadlocks\/","title":{"rendered":"Static constructor deadlocks"},"content":{"rendered":"<p>One important fact to know about static constructors is that they effectively execute under a lock. The CLR must ensure that each type&nbsp;is initialized exactly once, and so it uses locking&nbsp;to prevent multiple threads from&nbsp;executing the same static constructor.&nbsp;A caveat, however, is that executing the static constructor under a lock opens up the possibility of deadlocks. <\/p>\n<p>This&nbsp;example demonstrates the deadlock:<\/p>\n<p><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; using System.Threading;<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; class MyClass<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; {<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() { \/* Won&rsquo;t run&#8230; the static constructor deadlocks *\/&nbsp; }<\/span><\/p>\n<p><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; static MyClass()<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread thread = new Thread(arg =&gt; { });<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thread.Start();<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; thread.Join();<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p>In the example above, the static constructor waits for the helper thread to complete.&nbsp;The&nbsp;thread executing the static constructor holds some CLR-internal lock. Then, if the&nbsp;CLR needs to acquire&nbsp;the CLR-internal lock in order to execute the helper thread &#8211; and that seems to be exactly what happens &#8211; a deadlock will occur.<\/p>\n<p>This CLR behavior is defined in section 10.5.3.3 of the ECMA CLI specification:<\/p>\n<p style=\"padding-left: 30px\">&#8220;Type initialization alone shall not create a deadlock unless some code called from a type initializer (directly or indirectly) explicitly invokes blocking operations.&#8221;<\/p>\n<p>So, any operation that blocks the current thread in a static constructor potentially risks a deadlock. For example, just as waiting on threads can deadlock a static constructor, waiting on a task can have the same effect. And the same goes for <strong>Parallel.For<\/strong>, <strong>Parallel.ForEach<\/strong>, <strong>Parallel.Invoke<\/strong>, <strong>PLINQ queries<\/strong>, etc.<\/p>\n<p>This example uses Parallel.For and also deadlocks:<\/p>\n<p><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; using System.Threading.Tasks;<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; class MyClass<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; {<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() { \/* Won&rsquo;t run&#8230; the static constructor deadlocks *\/&nbsp; }<\/span><\/p>\n<p><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; static int s_value = ComputeValue();<\/span><\/p>\n<p><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; private static int ComputeValue()<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Action emptyAction = () =&gt; {};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parallel.Invoke(emptyAction, emptyAction);<br><\/span><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 42;<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<\/span><br><span style=\"font-family: courier new,courier\">&nbsp;&nbsp;&nbsp; }<\/span><\/p>\n<p>As this example shows, Parallel.For called from a static constructor can also cause a deadlock. Also, notice that in the example above, the Parallel.For is actually called from a static initializer, not a static constructor. For all intents and purposes, static initializers execute as a part of the static constructor, and so they are also at risk of the same kind of deadlock.<\/p>\n<p>So, to avoid the risk of deadlocks, avoid blocking the current thread in static constructors and initializers: don&rsquo;t wait on tasks, threads, wait handles or events, don&rsquo;t acquire locks, and don&rsquo;t execute blocking parallel operations like parallel loops, Parallel.Invoke and PLINQ queries.<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>One important fact to know about static constructors is that they effectively execute under a lock. The CLR must ensure that each type&nbsp;is initialized exactly once, and so it uses locking&nbsp;to prevent multiple threads from&nbsp;executing the same static constructor.&nbsp;A caveat, however, is that executing the static constructor under a lock opens up the possibility of [&hellip;]<\/p>\n","protected":false},"author":481,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[7908],"tags":[],"class_list":["post-56053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pfxteam"],"acf":[],"blog_post_summary":"<p>One important fact to know about static constructors is that they effectively execute under a lock. The CLR must ensure that each type&nbsp;is initialized exactly once, and so it uses locking&nbsp;to prevent multiple threads from&nbsp;executing the same static constructor.&nbsp;A caveat, however, is that executing the static constructor under a lock opens up the possibility of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56053","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/481"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=56053"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/56053\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=56053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=56053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=56053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}