如何安全地停止std线程?

时间:2013-12-19 12:27:40

标签: c++ multithreading join boost-asio

我正在开发一个聊天服务器,我有一个问题。

如何安全地停止std::thread

很容易出问题,就像这样。

thread t(&func);
t.join();

但是,如果func具有无限循环,则连接不起作用。

这是我的来源。

void CServerSocket::AcceptRun(boost::asio::io_service &iosrv)
{
    while (true)
    {
        auto sock = std::make_shared<boost::asio::ip::tcp::socket>(iosrv);
        m_Acceptor->accept(*sock);

        m_SocketList.push_back(std::make_shared<CConnectionSocket>(this, sock));
    }
}

CServerSocket::~CServerSocket()
{
    CLogManager::WriteLog("Stopping Server...");
    m_Acceptor->close();
    m_Acceptor.reset();

    // m_AcceptThread.detach(); This is right?

    CLogManager::WriteLog("Server Stoped!");
}

我很纳闷。 请帮我。 谢谢。

3 个答案:

答案 0 :(得分:8)

您可以将合适的上下文传递给您的线程,该线程可以包含一个标志,指示是否该停止。标志可以是std::atomic<bool>。显然,你还需要设置通信,不要无限期地等待数据,这样你就有机会偶尔检查一下标志。

答案 1 :(得分:3)

  

如何安全地停止std :: thread?

安全地停止线程意味着告诉线程函数停止处理(通过std::thread之外的机制),然后等待线程停止。

response from @DietmarKuhl告诉您如何执行此操作。关于acccept被阻塞,您必须在套接字/接受器上设置一个选项,以便在超时时间到期。当accept调用返回时,您要么中断循环(如果循环条件为false),要么再次调用accept,并使用新的超时。

你的超时值将是一个妥协:一个小的超时会更加计算密集(保持CPU忙),同时为你提供一个非常敏感的线程函数(当你停止线程时不会阻塞很多)。

答案 2 :(得分:3)

我很确定当你关闭接受器时accept会干净地退出,抛出异常。你应该捕获异常,以便线程正常退出:

void CServerSocket::AcceptRun(boost::asio::io_service &iosrv)
try {
    // your loop here, unchanged
} catch (std::exception const & ex) {
    // perhaps log the message, ex.what()
}

然后在关闭接受器之后加入线程,但在销毁它之前:

CServerSocket::~CServerSocket()
{
    CLogManager::WriteLog("Stopping Server...");
    m_Acceptor->close();
    m_AcceptThread.join();
    CLogManager::WriteLog("Server Stopped!");

    // No need to do anything else with m_Acceptor, assuming it's a smart pointer
}

就个人而言,除非有令人信服的理由使用多个线程,否则我会使用异步操作。单个线程更容易处理。