6

静的イニシャライザはスレッドセーフだと誰もが言いますが、私は特定の詳細について心配しています。

私が持っているとしましょう

static class MyStaticClass
{
    public static readonly object myField = MyOtherClass.GetNewObject();
}

static class MyOtherClass
{
    public static object GetNewObject()
    { /* arbitrary code that returns a new object */ }
}

MyStaticClass.myFieldがまだ初期化されていない場合、C# が保証するのは次のうちどれですか?

  1. myFieldスレッド 1 と 2 が一緒に (この順序で)アクセスしようとすると、スレッド 2 が読み取る前に実行GetNewObject開始さmyFieldれます。

  2. myFieldスレッド 1 と 2 が一緒に (この順序で)アクセスしようとすると、スレッド 2 が読み取る前に実行GetNewObject終了しmyFieldます。

一般的に CLR はどうですか? その保証が C# のものと異なる場合、それらはどのように異なるのでしょうか?
最近のバージョンの .NET Framework で動作が変更されましたか?

ノート:

これは難しい質問であり、完全な回答はおそらく静的コンストラクターと静的初期化子の違い、およびそれらがどのように相互作用しbeforefieldinitて要求された結果を生成するかについて言及すると思います。

4

2 に答える 2

3

ケース 2 は尊重されます。クラス フィールド、プロパティ、またはメソッドは、型が初期化されるまで逆参照できず、型は静的コンストラクターが完了するまで初期化されません。私の知る限り、静的コンストラクターはブロッキング呼び出しです。

http://msdn.microsoft.com/en-us/library/aa645612(v=vs.71).aspx

「クラスの静的コンストラクターは、特定のアプリケーション ドメインで最大 1 回実行されます。」

Eric Lippert からの返信: https://stackoverflow.com/a/9399027/2420979を参照してください。「cctor」は静的コンストラクターの IL であることに注意してください。

直接的または間接的に MyMethod を呼び出す CCTOR はありません。MyClass の cctor が完了する前に、MyMethod のような静的メソッドを呼び出すことは可能ですか?

いいえ。

複数のスレッドが関係している場合でも、それは当てはまりますか?

はい。静的メソッドが任意のスレッドで呼び出される前に、cctor は 1 つのスレッドで終了します。

cctor を複数回呼び出すことはできますか? 2 つのスレッドの両方で cctor が実行されるとします。

cctor は、関係するスレッドの数に関係なく、最大 1 回呼び出されることが保証されています。2 つのスレッドが MyMethod を「同時に」呼び出すと、競合が発生します。そのうちの 1 つが競争に負け、MyClass cctor が勝者のスレッドで完了するまでブロックします。

于 2013-06-26T21:30:30.683 に答える
2

MSDNから取得:

静的メンバーは、静的メンバーが初めてアクセスされる前、および静的コンストラクター (存在する場合) が呼び出される前に初期化されます。

2 番目のメソッドが 2 つの異なるスレッドで実行されているが、静的クラスを使用していない場合は、ビルドされません。ただし、参照がある場合は、2 つのスレッドのいずれかがアクセスする前に初期化されます。

于 2013-06-26T21:33:26.197 に答える