面试题答案
一键面试可能出现的并发问题
- 缓存一致性问题:在多处理器或具有缓存的系统中,CPU可能会将全局变量
flag
缓存到自己的高速缓存中。主程序循环执行任务时,可能一直在使用缓存中的旧值,而信号处理函数修改的flag
值在主存中,导致主程序不能及时感知到flag
的变化。 - 指令重排问题:编译器为了优化代码性能,可能会对指令进行重排。例如,主程序中对
flag
的读取操作可能被提前到循环的前面,导致即使flag
被信号处理函数修改,主程序也不会在循环中及时检测到变化。
使用volatile
关键字缓解问题
volatile
关键字告诉编译器,该变量的值可能会在程序的控制流之外被改变。在声明全局变量flag
时使用volatile
关键字,如下所示:
#include <stdio.h>
#include <signal.h>
volatile int flag = 0;
void sig_handler(int signum) {
flag = 1;
}
int main() {
signal(SIGINT, sig_handler);
while (1) {
// 执行任务
if (flag) {
printf("Received SIGINT, exiting loop...\n");
break;
}
}
return 0;
}
这样声明后,编译器不会对flag
进行缓存优化,每次访问flag
时都会从内存中读取最新值,避免了缓存一致性问题。同时,volatile
也会阻止编译器对涉及flag
的指令进行重排,确保程序按照代码逻辑执行,从而使主程序能及时感知到flag
的变化。