C++, запуск двух функций в параллельном и совместном режиме

У меня есть два метода, которые я хочу выполнить параллельно, данные передаются по константной ссылке.

Как только один из методов завершил свою работу, другому нет необходимости продолжать, так как один из них может иметь длительное время выполнения в зависимости от входа и поэтому должен остановиться.

Я обнаружил, что могу выполнять два метода параллельно, запустив два потока, используя <thread> заголовок, но мне пришлось ждать окончания обоих методов после их соединения.

Как я могу достичь этого типа параллельной обработки с таким совместным механизмом?

1 ответ

Решение

Я написал небольшой пример, чтобы показать, как это делается. Это не архивируется с join, как вы уже узнали. Вам нужно событие, о котором вы можете сообщить из потока, когда оно даст результат. Для этого вы должны использовать std::conditon_variable, Пример показывает минимально возможное решение для вашей описанной проблемы. В примере, простой результат в.

Есть две ловушки, которые вы должны заботиться.

Поток закончен до того, как основной ждет. По этой причине я блокирую мьютекс перед тем, как запускать потоки.

б. Результат перезаписывается. Мне удалось это, проверив результат, прежде чем писать.

#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
}
Другие вопросы по тегам