MST

星途 面试题库

面试题:C++ 信号处理函数与多线程交互

在多线程环境下使用C++信号处理函数会面临一些挑战。假设你有一个多线程程序,主线程负责监听`SIGTERM`信号,其他工作线程进行一些复杂的计算任务。当主线程捕获到`SIGTERM`信号时,如何安全且高效地通知工作线程停止任务并进行清理工作?请详细阐述思路,并给出关键代码片段。
40.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

思路

  1. 使用共享标志:定义一个共享的标志变量,主线程捕获到SIGTERM信号时,设置这个标志变量。工作线程定期检查这个标志,当标志被设置时,停止任务并进行清理。
  2. 线程同步:由于标志是共享的,需要使用线程同步机制(如互斥锁)来确保对标志的读写操作是线程安全的。
  3. 信号处理函数:在信号处理函数中,不能直接调用可能会引起未定义行为的函数(如printf等标准I/O函数)。因此,信号处理函数只负责设置共享标志,不进行复杂的清理工作。

关键代码片段

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

std::atomic<bool> stopFlag(false);
std::mutex mtx;

void workerThread() {
    while (!stopFlag.load()) {
        // 复杂的计算任务
        std::unique_lock<std::mutex> lock(mtx);
        std::cout << "Worker thread is working..." << std::endl;
        // 模拟工作
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    // 清理工作
    std::unique_lock<std::mutex> lock(mtx);
    std::cout << "Worker thread is cleaning up..." << std::endl;
}

void signalHandler(int signum) {
    stopFlag.store(true);
}

int main() {
    std::signal(SIGTERM, signalHandler);

    std::thread worker(workerThread);

    std::cout << "Main thread is waiting for SIGTERM..." << std::endl;
    // 主线程等待信号
    while (!stopFlag.load()) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    worker.join();

    std::cout << "Main thread is exiting..." << std::endl;
    return 0;
}

在上述代码中:

  • std::atomic<bool> stopFlag 用于存储停止标志,atomic类型保证了对该变量的读写操作是原子的,不需要额外的锁(这里atomic本身就线程安全)。
  • std::mutex mtx 用于保护cout输出,防止多线程同时输出导致混乱。
  • workerThread函数是工作线程,它在stopFlagfalse时执行计算任务,当stopFlag变为true时进行清理工作。
  • signalHandler函数是信号处理函数,捕获到SIGTERM信号时设置stopFlag
  • main函数中,主线程注册信号处理函数,启动工作线程,并等待stopFlag被设置,最后等待工作线程结束后退出。