C++std::连接前线程终止

C++ std::thread termination before join

本文关键字:终止 线程 连接 C++std 前线      更新时间:2024-05-10

我正在编写一个C++代码,在不同的线程上执行任务,并等待结果返回到主函数。

每个线程可能占用不同的时间,并可能导致正确或不正确的结果。

我按如下方式启动线程:

std::thread p1(&process1, (void*)&p1Data);
std::thread p2(&process2, (void*)&p2Data);
std::thread p3(&process3, (void*)&p3Data);
.
.
.

(通过这种方式创建多个线程(。

过程功能可以总结如下:

\ThreadData is a structure that contains all the data for the thread
void process1(void *data)
{
ThreadData * tData = (ThreadData*) data;
ResultObject * result = data->result;
.
.
.
\Process to calculate Result using data
}

在我启动这些线程之后,我加入它们,等待最终结果,然后检查正确的结果。

p1.join();
p2.join();
.
.
.
p1result = p1Data.result;
p2result = p2Data.result;
.
.
.
.
.
.
if (p1result)
{
return p1Data;
}
if (p2result)
{
return p2Data;
}

但问题是(为了简单起见,我认为p1是最快的线程(如果p1以正确的结果完成,我仍然被迫等待所有其他线程的连接以获得我的最终结果,而首先完成的p1可以包含正确的结果,我可以终止它。

完成后,我如何检查每个线程的结果是否正常,这样我就可以终止剩余的线程,而无需等待它们完成(即,如果p2在p1之前完成,并且p2的结果可以接受,我可以返回p2Data并终止所有剩余的线程而不需要(

不幸的是,没有std::shared_promise具有原子set_if_still_empty()is_empty()方法。此外,线程不能从外部终止(这是一件好事(,C++20用std::jthread及其停止标记解决了这个问题,可以随意使用。我将只使用std::atomic_bool标志。在这两种情况下,线程本身都必须监视令牌,并在请求时终止自身。

我的解决方案使用std::promise来存储结果,如果已经设置了结果,并且它的setter是原子的,它就会抛出,所以不需要额外的锁。

#include <future>
#include <thread>
#include <atomic>
using result_t=int;
void worker(std::promise<result_t>& promise,std::atomic_bool& stop_requested){
//periodically check flag
while(!stop_requested){
// do work

// if result
result_t result=1;
try{
promise.set_value(result);
// Terminate other threads soon, including us.
stop_requested=true;
return; // Not need if there is no work after `try` statement.
}
catch(const std::future_error&)//Already set
{
return;
}     
}
}
int main() {
std::promise<result_t> promise;
std::atomic_bool stop_token= false;
std::thread w1(worker,std::ref(promise),std::ref(stop_token));
auto future = promise.get_future();

result_t result = future.get();
// All threads should terminated soon after they check the token.
//stop_token=true;// Is not necessary because it is set by the winning thread.
w1.join();

}

或者,也可以使用std::optional<result_t>+锁。但是,您必须定期锁定以检查结果是否存在,线程是否应该退出。

您需要在线程本身中使用互斥实现同步机制。

当一个线程终止时,它可以告诉其他线程,他们可以提前终止(在线程内使用std::terminate(,只需锁定互斥对象,写入结果并释放互斥对象。然后,每个线程都必须查找它们是否可以以规则的间隔提前终止。

请参阅:如何在C++11中终止线程?