2

このコードには競合状態がありますか?

auto x = make_shared<Fun>(1984); //could also be raw ptr
auto t = thread(func, x);

また、ハーブ・サッター氏は C++ and Beyond での講演で並行キューを使用しました。

したがって、キューがある場合q

auto x  = new Fun(1984);
q.push(x);

//other thread 
auto ptr = q.pop();

これは競合状態ですか?他のスレッドがポップしても、指してptrいるメモリ位置の古い値が表示される可能性はありますか? ptr同時キューは標準ではないため、PPL/TBB を使用していると仮定します。

4

2 に答える 2

3

どちらの場合もいいえ。

最初の例は、のいくつかの特別なプロパティがなければ、原則std::threadとして明確な競合状態になります。コンパイラは、原則として移動の順序を変更できますが、スレッド オブジェクトの構築には順序の一貫性があり、それが機能することが正式に保証されます。しかし、そのプロパティがなかったとしても、実際にスレッドを作成して開始するには非常にかなりの時間がかかるため (いくつかの移動命令を実行するのに比べて数十万から数百万倍)、実質的には (形式的ではなく、実質的に)シーケンシャルな一貫性がなくても、競合がないことを保証する必要があります (この「実際的な保証」は確かに多少議論の余地があります。不自然な極端なケースでは当てはまらないかもしれませんが、正式な保証はどちらの方法でも当てはまります)。

2 番目の例では、定義上、競合状態が発生しないように (ロックまたはロックフリー アルゴリズムを使用して) 設計された同時キューを使用します。1

どちらの場合でも、最終的にキューに入れられるポインターは、まったく存在しないことが保証されます (その場合、pop操作はブロックされるか失敗します。「失敗」とは、利用可能な有効なポインターがないことを消費スレッドが認識していることを意味します)。現時点では -- 無効な値を想定していません) または有効な状態にあります。ポインターをキューに追加するアトミック (ロックまたはロックフリー) 操作は、以前に行われたオブジェクトの構築も以前に実現されることを保証します (つまり、有効なオブジェクトのないキューにはポインターがありません)。
これは、ポインターがキューから取得されたときにもオブジェクトが有効でなければならないことを意味します (チートしない限り)。


1これは明らかにキューの正しい操作を前提としていますが、それは公正な前提です。

于 2013-08-25T14:18:19.557 に答える
0

競合状態が発生する可能性がありますxが、それは、他のスレッドがそのコピーを使用するようになったときにポインターが使用された場合のみです。

このような関数:

void CreateWork(Queue& q){
    auto x  = new Fun(1984);
    // could use x here
    q.push(x);
}

xがキューに入ると、呼び出したスレッドはCreateWorkにアクセスできないため、競合状態があってはなりませんx

于 2013-08-25T14:05:34.347 に答える