如何在不阻塞主线程的情况下使用 join() 创建多个 C++ 线程?

Posted

技术标签:

【中文标题】如何在不阻塞主线程的情况下使用 join() 创建多个 C++ 线程?【英文标题】:How do I create multiple C++ threads without blocking the main thread using join()? 【发布时间】:2018-02-05 19:46:16 【问题描述】:

我在 C++ 中有一个简单的 TCP 客户端/服务器,我目前正在为每个连接的用户生成一个线程来处理消息,但是我遇到了一些问题,我不知道如何解决它们,因为我不熟悉标准 C++ 线程。

当客户端连接到服务器时,会为该客户端创建一个线程,直到它们使用类似的东西断开连接

clientThread = thread(processMessages);
clientThread.join();

此线程将在客户端的整个生命周期内持续存在。正如我在这个线程上调用了 join(),当 client 2 连接而 client 1 仍然连接时,它被 join() 调用阻止。

删除这个 join() 调用意味着当客户端断开连接时,线程被破坏,导致 terminate() 错误,因为它是可连接的。

我怎样才能让这个客户端线程只在后台处理,而主线程可以继续并接受新的连接?

【问题讨论】:

使用detach() 而不是join() 哇,谢谢,完全错过了。 我不推荐thread::detach() :-/。 std::future 可能是更好的建议。 在这种情况下使用detach 有点像建议有人切断他们的手臂以防止蚊虫叮咬。这里最大的问题是“为每个连接的用户生成一个线程”,众所周知,它工作得不好。我的建议是查找类似 ASIO 的东西,它可以以合理、可扩展的方式处理您的问题。如果您真的想自己做,请创建一个线程池和一个由线程池处理的请求队列。这可以大大减少开销。 如果您在创建后立即加入,那么一开始就创建一个线程没有多大意义。如果您正在创建一个新的thread,您可能希望并行或异步进行工作。因此,在工作线程工作时执行您需要主线程执行的任何操作,并且只有在您真正需要知道 thread 已完成时才使用 join 【参考方案1】:

仅展示如何存储创建的 thread 对象:

std::vector<std::thread> threads;
threads.emplace_back(processMessages);
...
for (auto & t : threads) t.join();

但是,正如其他人在 cmets 中指出的那样,为每个新连接创建一个线程可能不是最好的方法。

【讨论】:

以上是关于如何在不阻塞主线程的情况下使用 join() 创建多个 C++ 线程?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 C++/C 中的阻塞函数的情况下将值从线程返回到主函数

在不阻塞主线程的情况下更新 tableView

如何在不阻塞 UI 的情况下创建 UIView

如何在 iOS 的后台线程中运行 XMPP Room Join & Invite 进程

boost - thread.join() 停止用户界面

C++11多线程中的detach()join()joinable()