0

(VC++ 2010 を想定: (1) /volatile:ms を使用できる、(2) まだ std::atomic がない、(3) スレッドセーフな静的変数の初期化がない、(4) std::call_once がない)

単純な C ポインターがある場合は、毎回ロックのコストを回避するために、次の二重チェック ロック パターンを実装できます。

static volatile void * ptr = nullptr;

//...
if ( ptr == nullptr)
{
   // Acquire Lock
   if (ptr == nullptr)
   {
      // some code
      // ptr = ...; // init ptr
   }
   // Release Lock
}
// ....

VC++ 2005 以降、volatile は上記のコードが正しいことを確認します。コードが移植可能でなくても大丈夫だと仮定します。

ここで、プレーン ポインターを std::shared_ptr または boost::shared_ptr に置き換える必要があるとします。同じことを行うにはどうすればよいでしょうか。そのshared_ptrを揮発性にする方法は? 別の揮発性フラグが必要ですか?

4

3 に答える 3

4

C++11 には、 のアトミック アクセサー関数がありshared_ptrます。を使用するダブルチェック ロックを作成するにはshared_ptr、次のアクセサーを使用します。

static std::shared_ptr<MyType> ptr;
if (std::atomic_load(ptr) == 0) {
    // lock the lock
    if (std::atomic_load(ptr) == 0) {
        std::shared_ptr<MyType> local_ptr(new MyType);
        std::atomic_store(ptr, local_ptr);
    }
    // unlock the lock
}
return ptr;
于 2012-09-22T18:48:35.733 に答える
3

VC++ 2005 以降、volatile は上記のコードが正しいことを確認します。

いいえ、違います。volatileスレッド化や原子性とは何の関係もありません。

現在のコードは正しくなく、C++ 標準によって妥当な動作が保証されていません。

あなたのふりをロックするコードは一般的には機能しないため、shared_ptr他のスマート ポインターでは確実に機能しません。安価なロックが必要な場合は、ロックのないコーディング パターンを調べてください。

于 2012-09-22T18:41:08.650 に答える
1

C++ 2011 では、明示的な同期を使用する必要さえありません。6.7 [stmt.dcl] パラグラフ 4 によると、初期化はシステムによって同期されます。

変数の初期化中に制御が同時に宣言に入った場合、同時実行は初期化の完了を待ちます。

これは、次のstd::shared_ptr<T>ように初期化できることを意味しているようです。

{
    static std::shared_ptr<MyType> ptr(new MyType(/*...*/));
    // ...
}
于 2012-09-22T20:11:49.133 に答える