在循环中创建新线程是否安全?

时间:2014-12-15 12:21:58

标签: c++ multithreading

在循环中创建新线程是否安全?我试过这种方式:

std::thread thread(ClientLoop,clientSocket)

但是一旦函数返回它就会抛出错误。

while (true){
    cout << "Waiting for new connections" << endl;
    clientSocket = accept(listenSocket, nullptr, nullptr);
    cout << "Client connected" << endl;
    new thread(ClientLoop,clientSocket);                
}   

这种方式有效,但我想知道是否没有内存泄漏。感谢。

3 个答案:

答案 0 :(得分:28)

  

一旦函数返回它就会抛出错误

实际上,您不能销毁可连接的线程对象。如果您以后无需等待线程完成,请将其分离:

std::thread thread(ClientLoop,clientSocket);
thread.detach();
// OK to destroy now

如果您稍后需要加入,那么您必须将其存储在循环之外的地方,例如

std::vector<std::thread> threads;
while (whatever){
    clientSocket = accept(listenSocket, nullptr, nullptr);
    threads.emplace_back(ClientLoop,clientSocket);
}

// later
for (std::thread & t : threads) {
    t.join();
}

// OK to destroy now
threads.clear();
  

这种方式有效,但我想知道是否没有内存泄漏。

是的,那是漏洞。每个new创建一个线程对象,然后丢弃指针而不删除它或将其指定给智能指针来处理。正如评论中所提到的,它不仅会泄漏内存,还会泄漏线程句柄,这在某些系统上是一种更稀缺的资源;所以一段时间后你可能会发现你无法启动更多的线程。

分离线程是让它在后台运行而不会泄漏的方法。这会导致线程在完成时释放其资源。

答案 1 :(得分:9)

在循环中创建线程没有问题,但有可能 如果它是循环结束时破坏它的问题 一个局部变量。要合法地破坏,一个线程对象 必须detach编辑,join编辑或移动。如果你的线程是 简单地“开火,忘记”,你永远不必 之后与它们同步(即使是干净的关机) 在创建它之后,只需在线程上调用std::thread::detach。 否则,您可以将其放入std::vector<std::thread>,所以 你可以找到它并在以后加入它。

答案 2 :(得分:5)

看起来好像你不想管理线程的生命周期(这几乎总是一个错误)。

如果你真的想这样做,就这样做了:

while (true){
    cout << "Waiting for new connections" << endl;
    clientSocket = accept(listenSocket, nullptr, nullptr);
    cout << "Client connected" << endl;
    thread t(ClientLoop,clientSocket);
    t.detach(); // detach the actual thread from its std::thread handle
}