我如何以受控方式停止std :: thread

时间:2019-01-27 23:07:06

标签: multithreading c++17

我有一个程序,可以在其中启动多个长时间运行的线程(例如REST-API)。对于准备好的信号(例如SIGHUP),我希望能够干净地关闭所有线程(通过等待它们退出)。下面是thispointer article中的一些代码,这些代码说明了如何执行此操作的好主意

#include <thread>
#include <iostream>
#include <assert.h>
#include <chrono>
#include <future>

void threadFunction(std::future<void> futureObj)
{
     std::cout << "Thread Start" << std::endl;
     while (futureObj.wait_for(std::chrono::milliseconds(1)) == 
 std::future_status::timeout)
    {
        std::cout << "Doing Some Work" << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));

    }
    std::cout << "Thread End" << std::endl;

}
int main()
{

    // Create a std::promise object
    std::promise<void> exitSignal;

    //Fetch std::future object associated with promise
    std::future<void> futureObj = exitSignal.get_future();

    // Starting Thread & move the future object in lambda function by reference
    std::thread th(&threadFunction, std::move(futureObj));

    //Wait for 10 sec
    std::this_thread::sleep_for(std::chrono::seconds(10));

    std::cout << "Asking Thread to Stop" << std::endl;

    //Set the value in promise
    exitSignal.set_value();

    //Wait for thread to join
    th.join();

    std::cout << "Exiting Main Function" << std::endl;
    return 0;
}

但是,正如人们可能已经注意到的那样,此概念有一个严重的缺点:exitSignal必须在调用th.join()之前发出。

在要收听信号的情况下,例如使用signal(SIGHUP, callback),这当然是不切实际的。

我的问题是:关闭多个线程是否有更好的概念?我将如何处理它们?我认为使用promise并不是一个坏主意,我只是还没有找到解决问题的方法。

1 个答案:

答案 0 :(得分:0)

您可以在std :: condition_variable上使用std :: notify_all_at_thread_exit()。
这是一个示例:

#include <mutex>
#include <thread>
#include <condition_variable>

#include <cassert>
#include <string>

std::mutex m;
std::condition_variable cv;

bool ready = false;
std::string result; // some arbitrary type

void thread_func()
{
    thread_local std::string thread_local_data = "42";

    std::unique_lock<std::mutex> lk(m);

    // assign a value to result using thread_local data
    result = thread_local_data;
    ready = true;

    std::notify_all_at_thread_exit(cv, std::move(lk));

}   // 1. destroy thread_locals;
    // 2. unlock mutex;
    // 3. notify cv.

int main()
{
    std::thread t(thread_func);
    t.detach();

    // do other work
    // ...

    // wait for the detached thread
    std::unique_lock<std::mutex> lk(m);
    cv.wait(lk, [] { return ready; });

    // result is ready and thread_local destructors have finished, no UB
    assert(result == "42");
}

来源:cppreference.com