C++ 线程完成后在另一个线程中调用方法

C++ 线程完成后在另一个线程中调用方法,c++,multithreading,c++11,parallel-processing,C++,Multithreading,C++11,Parallel Processing,我正在尝试并行化我的程序,但由于我对线程非常陌生,所以我面临一些问题 我有两个属于同一类的方法。其中一个方法在for循环中执行一些计算并将结果推送到向量中,另一个方法(runTheResult)获取向量并使用获得的向量启动线程。我希望启动另一个线程,以便在每次运行结果时运行下一个获得的结果,同时将一次的最大线程数限制为4 我的程序结构如下: void runTheResult(vector<double>& u){ //process 'u' and launch a th

我正在尝试并行化我的程序,但由于我对线程非常陌生,所以我面临一些问题

我有两个属于同一类的方法。其中一个方法在for循环中执行一些计算并将结果推送到向量中,另一个方法(runTheResult)获取向量并使用获得的向量启动线程。我希望启动另一个线程,以便在每次运行结果时运行下一个获得的结果,同时将一次的最大线程数限制为4

我的程序结构如下:

void runTheResult(vector<double>& u){

//process 'u' and launch a thread 


};

void method(){

for(...){

//calculate

    for(...){

    //put the calculations in vector<double>result

    };

    runTheResult(result); 

};

};
void runTheResult(向量&u){
//处理“u”并启动线程
};
void方法(){
对于(…){
//算计
对于(…){
//将计算结果放入vectorresult
};
运行结果(result);
};
};
我在谷歌上搜索了很多,其中一个解决方案就是保持一条消息。然而,问题是,如果我实现了一个que,我必须在while循环中周期性地用另一个线程检查que。如果我使用while循环,比如
while(true){//如果线程数少于5个,则检查新消息}
,我将失去很多处理能力,如果我选择在不满足条件的情况下使循环休眠,我将浪费处理能力。我在线程中运行的函数每个都需要2-5秒,并且我必须处理~1k到50k个线程,因此每个循环即使延迟一秒也非常多


是否可以在每次完成runTheResult时在另一个线程中运行runTheResult?还是有更好的方法

其他人告诉您使用消息队列,因为这是最安全的方法。您的程序必须至少有一个用户(您或最终用户)可以与之交互的主线程。只要程序运行,这个主线程就会循环。您可以在这里进行消息处理

// this is not actually running the result now
// this only sends it to the main thread that will run the result
void runTheResult(vector<double>& u){ 

    //process 'u' and launch a thread. 
    // @NOTE Launching a thread again will not be beneficial as it will still be blocked 
    // by the mutex

    // convert/store vector into Message. To make it usable for other types
    // or you can just change Message to double
    Message u_message = to_message(u)

    std::lock_guard<std::mutex> lock(message_mutex);
    messages_shared.append(u_message);

};

void method() // runs on worker thread
{
    for(...){

    //put the calculations in vector<double>result

    };

    runTheResult(result);
}

void getMessages_safe(std::vector<Messages>& outMessages_safe)
{
    // as Ted Lyngo suggests, using lock_guard is best practice. See edit for alternative
    std::lock_guard<std::mutex> lock(message_mutex);
    outMessages_safe = messages_shared;
    messages_shared.clear();
}

std::vector<Message> messages_shared;
std::mutex message_mutex;

void main() { // this runs on the very first thread of the program
  while (isProgramRunning)
  {
      std::vector<Message> messages_safe; // safe to access by this thread only
      getMessages_safe(messages_safe);

      // dispatch messages to whoever needs it

      // launch worker thread
  }
}

//现在实际上没有运行结果
//这只会将其发送到将运行结果的主线程
void runTheResult(vector&u){
//处理“u”并启动线程。
//@NOTE再次启动线程不会有任何好处,因为它仍然会被阻止
//通过互斥
//将向量转换/存储为消息。使其可用于其他类型
//或者你可以把信息改成双倍
消息u\u Message=发送消息(u)
std::lock\u guard lock(消息互斥);
消息共享。追加(消息);
};
void method()//在工作线程上运行
{
对于(…){
//将计算结果放入vectorresult
};
运行结果(result);
}
void getMessages_safe(std::vector&outMessages_safe)
{
//正如Ted Lyngo所建议的,使用锁护是最佳实践。请参阅编辑以获取替代方案
std::lock\u guard lock(消息互斥);
outMessages\u safe=共享的消息;
消息共享。清除();
}
std::矢量消息共享;
std::互斥消息\u互斥;
void main(){//它在程序的第一个线程上运行
while(isprogram正在运行)
{
std::vector messages_safe;//只能通过此线程安全访问
获取安全消息(安全消息);
//向任何需要它的人发送消息
//启动工作线程
}
}

您可以让另一个线程等待一个条件变量并唤醒它,然后根据您将设置的一些标志执行您想要的函数。在Windows中,您还可以拥有消息队列并发布消息(不是您创建的for循环,而是GetMessage())。对于简单的多线程计算,您还可以使用future/promise.Create 4个线程并让它们等待条件变量。每次您为其中一个线程准备好工作时,调用
notify_one
@MichaelChourdakis如果我检查标志,我仍然必须使用while循环,对吗?如果您不介意的话,您能详细说明一下吗?关键是,通过使用这些“等待”对象,for循环不会消耗系统资源。如果等待条件变量,那么在等待期间线程不会占用CPU。您将执行for循环,但在该循环中,您将检查条件变量,如果已设置,则检查标志。在我以前的一篇文章中提供了更多信息。为什么不为互斥体使用适当的保护?如果抛出
messages\u shared.append()
,如果您执行上述操作,互斥锁将被永久锁定<代码>标准::锁定保护(消息互斥);消息共享。追加(消息)则不需要手动解锁。看起来没有人在等待条件变量,所以至少有一个线程会疯狂地旋转。这是真的。但这不是问题的主要主题。我使用了最明确的方式来使用互斥,因为我不知道op是否知道。op似乎非常关心性能,所以当它可以做其他事情(比如操作系统)时,将处理器浪费在旋转上是不好的。此外,在处理线程时,锁保护和条件变量几乎是必须的,因此我相信,如果您将它们引入示例中,OP将了解它们的好处。我已经编辑了我的答案,以使用
lock\u guard
。但是我想不出一种方法来实现条件变量,而不使程序成为一个单独的执行程序,并且以后无法启动新线程。关于
condition\u variable
s当有人将消息放入
messages\u shared
中时,它可以
notify\u one
,主线程可以等待,而不是一次又一次地尝试获取不在那里的消息。