C++14 (別名 C++1y) に含めることが提案されているのは、いくつかの新しいスレッド同期プリミティブ (ラッチとバリア) です。提案は
良いアイデアのように思えますし、サンプルを見ると非常にプログラマーフレンドリーに見えます。残念ながら、サンプル コードは未定義の動作を呼び出すと思います。提案は次のように述べていlatch::~latch()
ます:
ラッチを破棄します。他のスレッドが にある
wait()
、または呼び出している間にラッチが破棄された場合count_down()
、動作は未定義です。
使用の説明として、wait()
「ブロックされている」ではなく「で」と表示されていることに注意してください。wait()
count_down()
次に、次のサンプルが提供されます。
2 番目のユースケースの例を以下に示します。データをロードしてから、多数のスレッドを使用して処理する必要があります。データのロードは I/O バウンドですが、スレッドの開始とデータ構造の作成は CPU バウンドです。これらを並行して実行することで、スループットを向上させることができます。
void DoWork() { latch start_latch(1); vector<thread*> workers; for (int i = 0; i < NTHREADS; ++i) { workers.push_back(new thread([&] { // Initialize data structures. This is CPU bound. ... start_latch.wait(); // perform work ... })); } // Load input data. This is I/O bound. ... // Threads can now start processing start_latch.count_down(); }
wait()
スレッドのウェイクアップと からの復帰、およびスコープを離れるときのラッチの破壊との間に競合状態はありませんか? それに加えて、すべてのthread
オブジェクトがリークされます。count_down
スケジューラが返される前にすべてのワーカー スレッドを実行せず、start_latch
オブジェクトがスコープを離れる場合、未定義の動作が発生すると思います。おそらく、修正はベクトルとjoin()
すべてdelete
のワーカースレッドを繰り返してcount_down
から返すことです。
- サンプルコードに問題はありますか?
- レビュアーが使用体験がどのようなものになるかを確認するために、タスクが非常に単純であっても、提案は完全に正しい例を示すべきであることに同意しますか?
注: 1 つ以上のワーカー スレッドがまだ待機を開始していない可能性があるためwait()
、破棄されたラッチを呼び出します。
更新: 現在、提案の新しいバージョンがありますが、代表的な例は変更されていません。