如何在不阻塞主线程的情况下使用 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 中的阻塞函数的情况下将值从线程返回到主函数