1

並行して実行したい 2 つのメソッドがあり、データは const 参照によって渡されます。

メソッドの 1 つがジョブを終了するとすぐに、もう 1 つのメソッドを続行する必要はありません。エントリによっては、メソッドの 1 つの実行時間が長くなり、停止する必要があるためです。

ヘッダーを使用して 2 つのスレッドを実行することで、2 つのメソッドを並行して実行できることがわかりましたが<thread>、結合した後、両方のメソッドが終了するまで待たなければなりませんでした。

このような協調メカニズムを使用して、この種の並列処理をどのように実現できますか?

4

1 に答える 1

4

それがどのように行われるかを示すために、小さなサンプルを書きました。すでにわかっているように、結合ではアーカイブできません。結果が得られたときに、スレッドから通知できるイベントが必要です。そのためには、を使用する必要があります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
}
于 2015-05-02T13:07:15.010 に答える