8

今日、私たちのコードベースでいくつかのシングルトン コードに出くわしましたが、以下がスレッドセーフかどうか確信が持てませんでした:

public static IContentStructure Sentence{ 
    get {
       return _sentence ?? (_sentence = new Sentence()); 
    }
}

このステートメントは次と同等です。

if (_sentence != null) {
       return _sentence;
}
else {
    return (_sentence = new Sentence());
}

私は信じている ??単なるコンパイラのトリックであり、結果のコードはまだアトミックではありません。つまり、_sentence を新しい Sentence に設定して返す前に、2 つ以上のスレッドが _sentence が null であることを検出する可能性があります。

原子性を保証するには、そのコードをロックする必要があります。

public static IContentStructure Sentence{ 
    get {

       lock (_sentence) { return _sentence ?? (_sentence = new Sentence()); }
    }
}

それはすべて正しいですか?

4

3 に答える 3

13

あなたは正しいです; スレッドセーフではありません。

于 2012-02-23T19:58:41.110 に答える
1

Interlocked.CompareExchangeを使用して、アトミックな操作nullを取得できます。??

// I made up my own Sentence type
Sentence current = null;
var whenNull = new Sentence() {Text = "Hello World!"};

var original = Interlocked.CompareExchange(ref current, new Sentence() { Text = "Hello World!" }, null);

Assert.AreEqual(whenNull.Text, current.Text);
Assert.IsNull(orig);

// try that it won't override when not null
current.Text += "!";
orig = Interlocked.CompareExchange(ref current, new Sentence() { Text = "Hello World!" }, null);

Assert.AreEqual("Hello World!!", current.Text);
Assert.IsNotNull(orig);
于 2012-02-23T20:07:03.013 に答える