どちらの場合もいいえ。
最初の例は、のいくつかの特別なプロパティがなければ、原則std::thread
として明確な競合状態になります。コンパイラは、原則として移動の順序を変更できますが、スレッド オブジェクトの構築には順序の一貫性があり、それが機能することが正式に保証されます。しかし、そのプロパティがなかったとしても、実際にスレッドを作成して開始するには非常にかなりの時間がかかるため (いくつかの移動命令を実行するのに比べて数十万から数百万倍)、実質的には (形式的ではなく、実質的に)シーケンシャルな一貫性がなくても、競合がないことを保証する必要があります (この「実際的な保証」は確かに多少議論の余地があります。不自然な極端なケースでは当てはまらないかもしれませんが、正式な保証はどちらの方法でも当てはまります)。
2 番目の例では、定義上、競合状態が発生しないように (ロックまたはロックフリー アルゴリズムを使用して) 設計された同時キューを使用します。1
どちらの場合でも、最終的にキューに入れられるポインターは、まったく存在しないことが保証されます (その場合、pop
操作はブロックされるか失敗します。「失敗」とは、利用可能な有効なポインターがないことを消費スレッドが認識していることを意味します)。現時点では -- 無効な値を想定していません) または有効な状態にあります。ポインターをキューに追加するアトミック (ロックまたはロックフリー) 操作は、以前に行われたオブジェクトの構築も以前に実現されることを保証します (つまり、有効なオブジェクトのないキューにはポインターがありません)。
これは、ポインターがキューから取得されたときにもオブジェクトが有効でなければならないことを意味します (チートしない限り)。
1これは明らかにキューの正しい操作を前提としていますが、それは公正な前提です。