启动多个线程而不加入它们

11

我该如何像这样启动多个线程:

for (i = 0; i < 10; i++) {
   std::thread (myfunction, i, param2, param3);
}

没有加入?


2
就像这样。加入不会启动线程。它会阻塞直到它们完成。 - juanchopanza
当我这样做时,在Visual Studio中会出现调试错误...R6010 abort()已经被调用了 :( - Niklas Hantke
4
在离开线程作用域之前,您需要加入或分离线程。只要注意一旦您分离线程,就无法稍后加入。我建议将线程对象放入向量中,稍后再进行加入操作。 - John5342
1
关于分离线程,请参见http://en.cppreference.com/w/cpp/thread/thread/detach。 - stefaanv
非常感谢所有人,特别是stefaanv和John5342! - Niklas Hantke
3个回答

18

试试这个

for (int i = 0; i < 10; ++i) {
    std::thread{myfunction, i, param2, param3}.detach();
}

如果您希望稍后加入线程,则可以将它们放在一个std::vector中。

std::vector<std::thread> v;
for (int i = 0; i < 10; ++i) {
    v.emplace_back(myfunction, i, param2, param3);
}

// Do something else...

for (auto& t : v) {
    t.join();
}

线程在添加到向量时启动,我认为 - 是否可能添加它们而不启动它们? - serup
@serup 当线程对象构造完成时,执行线程将开始。可以查看std::async以进行惰性评估。或者,可以存储可调用对象,然后在需要启动时创建线程。 - Felix Glas

7

只需不调用join(),改用detach()


4
可以稍微详细地解释一下detach()的含义吗? - serup
3
detach()允许线程独立运行。join()会阻塞父线程直到它完成。 - Noi Doan

0

当然你可以创建一些线程而不加入它们,就像你平常所做的那样:

for (i = 0; i < 10; i++) {
  std::thread my_thread {myfunction, i, param2, param3};
}

一旦创建了一个线程,它就开始被安排运行或等待。然而,我建议你不要这样做。

"join" 的意思是要求当前线程等待您调用 join 的线程。例如:

#include <iostream> 
#include <thread> 
using namespace std; 

// A dummy function 
void foo(int n) 
{ 
  cout << "This is a dummy function." << endl; 
}

// Another dummy function
void bar(char c) {
  cout << "This is another dummy function." << endl;
} 

int main() 
{
  thread foo_thread(foo, 2); 
  thread bar_thread(bar, 'x');

  foo_thread.join();  // wait for foo_thread to finish
  bar_thread.join();  // wait for bar_thread to finish

  return 0; 
} 

主线程将休眠,直到foo_thread和bar_thread完成。

如果您删除foo_thread.join()和bar_thread.join(),则主线程可能会在foo和bar之前完成并返回。这将导致程序崩溃。因为在main函数结束时,将调用foo_thread和bar_thread的析构函数,并且std::thread的析构函数将检查该线程是否可连接。如果线程未分离,则可连接。如果线程可连接,则析构函数将调用std::terminate(),从而导致程序崩溃。


析构函数为什么会调用std::terminate?可加入线程的析构函数会调用join,因此即使删除foo_thread.join()bar_thread.join(),该程序的行为也应完全相同。 - Ap31
1
@Ap31 不,可加入线程的析构函数不会调用join()。根据C++11规范30.3.1.3,“如果joinable(),则调用std::terminate()。否则,没有任何影响”。因此,如果您删除foo_thread.join()和bar_thread.join(),程序将被终止。 - Yan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接