У меня есть два метода, которые я хочу выполнить параллельно, данные передаются по константной ссылке.
Как только один из методов завершил свою работу, для другого нет необходимости продолжать, так как один из них может иметь длительное время выполнения в зависимости от входа и поэтому должен остановиться.
Я обнаружил, что могу выполнять два метода параллельно, запустив два потока, используя <thread>
заголовок, но мне пришлось ждать окончания обоих методов после их соединения.
Как я могу достичь этого типа параллельной обработки с таким совместным механизмом?
Я написал небольшой пример, чтобы показать, как это делается. Это не архивируется с 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
}