それがどのように行われるかを示すために、小さなサンプルを書きました。すでにわかっているように、結合ではアーカイブできません。結果が得られたときに、スレッドから通知できるイベントが必要です。そのためには、を使用する必要がありますstd::conditon_variable。このサンプルは、説明した問題に対する最小限の解決策を示しています。サンプルでは、結果は単純な入力です。
注意しなければならない落とし穴が 2 つあります。
a.メインが待機する前にスレッドが終了します。そのため、スレッドを開始する前にミューテックスをロックします。
b. 結果は上書きされます。私はそれを書く前に結果をテストすることでそれを管理しました。
#include <thread>
#include <condition_variable>
#include <mutex>
std::mutex mtx;
std::condition_variable cv;
int result = -1;
void thread1()
{
// Do something
// ....
// ....
// got a result? publish it!
std::unique_lock<std::mutex> lck(mtx);
if (result != -1)
return; // there is already a result!
result = 0; // my result
cv.notify_one(); // say I am ready
}
void thread2()
{
// Do something else
// ....
// ....
// got a result? publish it!
std::unique_lock<std::mutex> lck(mtx);
if (result != -1)
return; // there is already a result!
result = 1; // my result
cv.notify_one(); // say I am ready
}
int main(int argc, char * argv[])
{
std::unique_lock<std::mutex> lck(mtx); // needed so the threads cannot finish befor wait
std::thread t1(thread1), t2(thread2);
cv.wait(lck); // wait until one result
// here result is 0 or 1;
// If you use the loop described below, you can use join safely:
t1.join();
t2.join();
// You have to call join or detach of std::thread objects before the
// destructor of std::thread is called.
return 0;
}
一方がすでに結果を持っている場合にもう一方のスレッドを停止したい場合、唯一の正当な方法は、両方のスレッドで結果を頻繁にテストし、誰かがすでに結果を持っている場合は停止することです。この場合、ポインターまたはジェネリック型を使用する場合は、volatile修飾子でマークする必要があります。ループ内で作業を行う必要がある場合、スレッド関数は次のようになります。
void thread1()
{
// Do something
bool bFinished=false;
while(!bFinished)
{
{ // this bracket is necessary to lock only the result test. Otherwise you got a deadlock a forced sync situation.
std::unique_lock<std::mutex> lck(mtx);
if (result != -1)
return; // there is already a result!
}
// do what ever you have to do
}
// got a result? publish it!
std::unique_lock<std::mutex> lck(mtx);
if (result != -1)
return; // there is already a result!
result = 0; // my result
cv.notify_one(); // say I am ready
}