C ++,信号和线程

Vuz*_*uzi 5 c++ multithreading signals c++11

我在使用线程和信号设计应用程序的主要工作流时遇到了一些困难。

我的目标是要有一个主线程,捕获信号以及n个其他线程定期执行操作(实际上是在树莓派上使用传感器,并保存检索到的数据)。我希望能够以一种干净的方式关闭程序,即在关闭传感器之前等待传感器完成数据写入(如果它们是在发生信号时)。我正在使用C ++ 11。

现在,我有这个例子:

#include <iostream>
#include <thread>
#include <csignal>
#include <mutex>

#define NUM_THREAD 3;

static volatile int stop = 0;     // If the threads needs to stop
std::mutex m;                     // Mutex

void threadHandle(int tid) {
    while(1) {
        std::cout << "Launched by thread " << tid << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << "I have sleep well " << tid << std::endl;

        m.lock();
        if(stop) {
            std::cout << "Thread " << tid << " needs to stop" << std::endl;
            m.unlock();
            break;
        }
        m.unlock();
    }
}

void signalHandler(int signum) {
    m.lock();
    std::cout << "Signal " << signum << " received" << std::endl;
    stop = 1;
    m.unlock();
}

int main() {
    std::thread t[NUM_THREAD];
    std::signal(SIGINT, signalHandler);

     //Launch a group of threads
     for (int i = 0; i < NUM_THREAD; i++) {
         t[i] = std::thread(call_from_thread, i);
     }

     std::cout << "Launched from the main\n";

     for (int i = 0; i < NUM_THREAD; i++) {
         t[i].join();
     }

     return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的止损值是可变的,仅因为我在信号处理程序中使用了它。我应该使用std :: atomic_int来确保原子调用信号值吗?互斥量真的有必要吗?或更笼统地说,这是实现我想要的一个好方法吗?

我可能遇到的另一个问题是,某些传感器在两次测量之间的等待时间可能会很长(例如2或3个小时),因此我需要每2或3秒检查一次停止值..感觉真的很干净。另一种解决方案是向线程发送信号,使我可以简单地使线程“休眠”。但是同样,我没有控件可以告诉线程在终止之前完成其操作。

提前致谢 !

Tsy*_*rev 5

信号处理程序中不允许对互斥体进行操作。您可以将stop变量分成两个:

  1. stop_main,在信号处理程序中设置,并在主线程中等待。因为信号处理程序是在主线程的上下文中执行的,所以将其声明为volatile(或std::atomic)就足够了。
  2. stop_threads,它在主线程中设置,并被其他线程等待。此变量最合适的类型是std::condition_variable。这种类型也有助于您长时间的等待。

像这样的东西:

std::atomic<int> stop_main = 0;
std::condition_variable stop_threads;
std::mutex m; // protects 'stop_threads'

void threadHandle(int tid)
{
    while(1)
    {
        /* .. do something .. */

        std::unique_lock<std::mutex> l(m);
        if(stop_threads.wait_for(l, std::chrono::hours(2)) ==
            std::cv_status::no_timeout) break;
    }
}
void signalHandler(int signum)
{
    stop_main.store(1);
}
int main()
{
    std::thread t[NUM_THREAD];
    std::signal(SIGINT, signalHandler);

    for (int i = 0; i < NUM_THREAD; i++) {
        t[i] = std::thread(threadHandle, i);


    while(!stop_main.load())
    {
        /* Some workload may be here */
        sleep(10); // Signals will interrupt this function.
    }

    stop_threads.notify_all();

    for (int i = 0; i < NUM_THREAD; i++) {
        t[i].join();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我不确定 c++ 是否保证信号传递到主线程,而不是其他线程。否则你需要阻塞其他线程中的信号。

sleep(10)主线程中的内容可以替换为任何可被信号中断的函数。