面试题答案
一键面试思路
- 使用共享标志:定义一个共享的标志变量,主线程捕获到
SIGTERM
信号时,设置这个标志变量。工作线程定期检查这个标志,当标志被设置时,停止任务并进行清理。 - 线程同步:由于标志是共享的,需要使用线程同步机制(如互斥锁)来确保对标志的读写操作是线程安全的。
- 信号处理函数:在信号处理函数中,不能直接调用可能会引起未定义行为的函数(如
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
函数是工作线程,它在stopFlag
为false
时执行计算任务,当stopFlag
变为true
时进行清理工作。signalHandler
函数是信号处理函数,捕获到SIGTERM
信号时设置stopFlag
。main
函数中,主线程注册信号处理函数,启动工作线程,并等待stopFlag
被设置,最后等待工作线程结束后退出。