C#のstaticなコンストラクタは、staticなメンバやそのクラスのインスタンス作成に先んじて実行されます。これは、1プロセス上に1つしかない様々な資源の初期化に便利ではありますが。
はたと不安になったことがありました。マルチスレッド環境だと何が起こるのでしょうか。たとえば、クラスCのstaticなメンバー変数Vにアクセスするスレッドが2つ走っていたとします。片方のスレッドがメンバー変数Vに最初にアクセスした時に、コンストラクタの実行が開始されますが、それが完了する前にもう1つのスレッドがメンバー変数Vにアクセスしたら何が起こるのでしょうか。
using System;
using System.Threading;
namespace ConsoleApplication2
{
public class TestClass
{
public static int A = 0;
static TestClass()
{
Console.WriteLine("TestClassコンストラクタ called");
Console.WriteLine("A(1)={0}",A);
Thread.Sleep( TimeSpan.FromSeconds(3) );
Console.WriteLine("A(2)={0}",A);
}
}
class Class1
{
public static void ThreadProc1()
{
Console.WriteLine("ThreadProc1 called");
TestClass.A ++;
Console.WriteLine("A(3)={0}",TestClass.A);
}
public static void ThreadProc2()
{
Console.WriteLine("ThreadProc2 called");
Thread.Sleep( TimeSpan.FromSeconds(1) );
TestClass.A ++;
Console.WriteLine("A(4)={0}",TestClass.A);
}
[STAThread]
static void Main(string[] args)
{
Thread t1 = new Thread(new ThreadStart(ThreadProc1));
Thread t2 = new Thread(new ThreadStart(ThreadProc2));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
}
}
}
このプログラムは、ThreadProc1が変数Aにアクセスしてstaticなコンストラクタを起動させ、その実行中にThreadProc2が変数Aの書き換えに行く、というものです。もし、正しく全てのアクセスがコンストラクタ実行完了まで待たされていれば、A(2)=0という結果を得るはずです。コンストラクタ実行中に変数を書き換えることができたなら、A(2)=1という結果になるはずです。