EYa*_*umi 1 c++ multithreading
我正在编写 C++ 代码来在不同线程上执行任务并等待结果返回主函数。
每个线程可以采取不同的计时,并可能导致正确或不正确的结果。
我按如下方式启动线程:
std::thread p1(&process1, (void*)&p1Data);
std::thread p2(&process2, (void*)&p2Data);
std::thread p3(&process3, (void*)&p3Data);
.
.
.
Run Code Online (Sandbox Code Playgroud)
(多个线程就是这样创建的)。
流程功能可以总结如下:
\\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
}
Run Code Online (Sandbox Code Playgroud)
在启动这些线程后,我将在 main 中加入它们以等待最终结果,然后检查正确的结果。
p1.join();
p2.join();
.
.
.
p1result = p1Data.result;
p2result = p2Data.result;
.
.
.
.
.
.
if (p1result)
{
return p1Data;
}
if (p2result)
{
return p2Data;
}
Run Code Online (Sandbox Code Playgroud)
但问题是(为了简单起见,我将认为 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存储结果,如果结果已设置且其设置器是原子的,则会抛出异常,因此不需要额外的锁。
#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();
}
Run Code Online (Sandbox Code Playgroud)
或者,std::optional<result_t>也可以使用+lock。但是您必须定期锁定以检查结果是否存在以及线程是否应该退出。