web-dev-qa-db-ja.com

Meyersのシングルトンパターンスレッドの実装は安全ですか?

レイジー初期化を使用したSingleton(マイヤーズシングルトン)スレッドセーフの次の実装は安全ですか?

static Singleton& instance()
{
     static Singleton s;
     return s;
}

そうでない場合、スレッドセーフにする理由と方法は?

126
Ankur

C++ 11 では、スレッドセーフです。 standard§6.7 [stmt.dcl] p4

変数の初期化中に制御が同時に宣言に入ると、同時実行は初期化の完了を待機します

機能のGCCおよびVSのサポート( 動的初期化および同時実行による破壊 、別名 Magic Statics on MSDN )は次のとおりです:

@Mankarseと@olen_gamのコメントに感謝します。


C++ 03 では、このコードはスレッドセーフではありませんでした。 Meyersによる "C++ and the Double-Checked Lockingの危険" という記事があり、パターンのスレッドセーフな実装について説明しています。結論は多かれ少なかれ( C++ 03)では、インスタンス化メソッドの周りの完全ロックは、基本的にすべてのプラットフォームで適切な同時実行性を確保する最も簡単な方法ですが、ほとんどの形式のダブルチェックロックパターンバリアントは、特定のアーキテクチャ上の 競合状態に苦しむ可能性があります 、命令がメモリ障壁を戦略的に配置することでインターリーブされない限り。

148
Groo

次の標準(セクション6.7.4)を見ると、静的なローカル初期化がスレッドセーフであることがわかります。そのため、標準のそのセクションが広く実装されると、Meyer's Singletonが推奨される実装になります。

私はすでに多くの答えに同意しません。ほとんどのコンパイラはすでにこの方法で静的初期化を実装しています。 1つの注目すべき例外は、Microsoft Visual Studioです。

9
deft_code

正しい答えはコンパイラによって異なります。 makeスレッドセーフにすることを決定できます。 「自然に」スレッドセーフではありません。

6
MSalters

次の実装は[...]スレッドセーフですか?

ほとんどのプラットフォームでは、これはスレッドセーフではありません。 (C++標準はスレッドについて知らないことを説明する通常の免責事項を追加します。したがって、合法的に、スレッドがそうであるかどうかはわかりません。)

そうでない場合、なぜ[...]?

そうではない理由は、複数のスレッドがs 'コンストラクターを同時に実行することを妨げるものがないからです。

スレッドセーフにする方法は?

"C++とダブルチェックロックの危険" Scott MeyersとAndrei Alexandrescuによるスレッドセーフシングルトンのテーマに関する非常に優れた論文です。

5
sbi

MSaltersが言ったように、それは使用するC++実装に依存します。ドキュメントを確認してください。他の質問に関して:「そうでない場合、なぜ?」 -C++標準では、スレッドについては何も言及されていません。しかし、次期C++バージョンはスレッドを認識しており、静的ローカルの初期化はスレッドセーフであると明示的に述べています。 2つのスレッドがそのような関数を呼び出すと、1つのスレッドが初期化を実行し、もう1つのスレッドがブロックして終了するまで待機します。

2
sellibitze