11

C ++ 11の新しいマシンモデルにより、マルチプロセッサシステムが確実に機能するようになります。指示の再編成に。

MeyersとAlexandrescuが指摘したように、「単純な」ダブルチェックロックパターンの実装はC++03では安全ではありません。

Singleton* Singleton::instance() {
  if (pInstance == 0) { // 1st test
    Lock lock;
    if (pInstance == 0) { // 2nd test
      pInstance = new Singleton;
    }
  }
  return pInstance;
}

彼らは彼らの記事で、プログラマーとして何をしても、C ++ 03ではコンパイラーの自由度が高すぎることを示しました。つまり、1つだけになるかどうか確信が持てない方法で命令を並べ替えることができます。のインスタンスSingleton

私の質問は今です:

  • 新しいC++11マシンモデルの制限/定義により、命令のシーケンスが制約され、上記のコードは常にC ++ 11コンパイラで機能しますか?
  • 安全なC++11-このシングルトンパターンの実装は、(ここのモックの代わりに)新しいライブラリ機能を使用するとどのようになりLockますか?
4

3 に答える 3

5

が通常のポインターである場合pInstance、コードには潜在的なデータ競合があります-ポインター(または、さらに言えば、任意の組み込み型)での操作は、アトミックであることが保証されていません(EDIT:または順序が正しい)

pInstanceがでありstd::atomic<Singleton*> Lock内部でを使用して同期を実現する場合std::mutex(たとえば、Lockが実際にである場合std::lock_guard<std::mutex>)、コードはデータ競合がない必要があります。

適切な同期を実現するには、明示的なロックとアトミックの両方が必要であることに注意してください。pInstance

于 2011-05-15T15:13:05.397 に答える
4

静的変数の初期化はスレッドセーフであることが保証されているため、Meyerのシングルトンはスレッドセーフである必要があります。

Singleton* Singleton::instance() {
  static Singleton _instance;
  return &_instance;
}

次に、主な問題に対処する必要があります。コードにシングルトンが含まれています。

編集:以下の私のコメントに基づく:この実装には、他の実装と比較した場合に大きな欠点があります。コンパイラがこの機能をサポートしていない場合はどうなりますか?コンパイラは、警告を発行することなく、スレッドセーフでないコードを吐き出します。コンパイラが新しいインターフェイスをサポートしていない場合、ロックを使用する他のソリューションはコンパイルされません。これは、シングルトン以外の場合でも、この機能に依存しないのに十分な理由かもしれません。

于 2013-09-05T13:22:17.857 に答える
1

C ++ 11は、ダブルチェックロックの実装の意味を変更しません。ダブルチェックのロックを機能させたい場合は、適切なメモリバリア/フェンスを建てる必要があります。

于 2011-05-15T13:44:30.063 に答える