面试题答案
一键面试虚假唤醒的定义
虚假唤醒(spurious wakeup)是指在条件变量等待的线程,在没有其他线程调用 pthread_cond_signal
或 pthread_cond_broadcast
来明确唤醒它的情况下,就从 pthread_cond_wait
调用中返回的现象。
虚假唤醒出现的原因
- 操作系统调度:操作系统的线程调度策略可能导致这种情况。在某些情况下,系统可能会错误地唤醒等待条件变量的线程,即使没有其他线程明确地发出唤醒信号。
- 信号处理:信号处理也可能与条件变量的等待机制相互干扰,从而导致虚假唤醒。
处理虚假唤醒的方法及代码示例
为了处理虚假唤醒,在从 pthread_cond_wait
返回后,应该再次检查条件是否满足,而不是直接认为条件已经满足。以下是一个使用条件变量实现线程同步并处理虚假唤醒的示例代码:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
// 共享资源
int shared_variable = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
// 线程函数
void* thread_function(void* arg) {
pthread_mutex_lock(&mutex);
// 等待条件变量,处理虚假唤醒
while (shared_variable == 0) {
printf("Thread waiting...\n");
pthread_cond_wait(&cond, &mutex);
}
printf("Thread awakened, shared_variable = %d\n", shared_variable);
pthread_mutex_unlock(&mutex);
return NULL;
}
int main() {
pthread_t thread;
// 创建线程
if (pthread_create(&thread, NULL, thread_function, NULL) != 0) {
perror("pthread_create");
return 1;
}
// 主线程模拟一些工作
sleep(2);
pthread_mutex_lock(&mutex);
shared_variable = 1;
printf("Main thread setting shared_variable and signaling...\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
// 等待线程结束
if (pthread_join(thread, NULL) != 0) {
perror("pthread_join");
return 2;
}
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
在上述代码中:
- 线程函数
thread_function
:通过while (shared_variable == 0)
循环来检查条件,确保只有当shared_variable
确实为非零(条件满足)时才继续执行,从而处理了虚假唤醒的情况。 - 主线程:在设置
shared_variable
为 1 后,调用pthread_cond_signal
唤醒等待的线程。
这样通过在 pthread_cond_wait
后使用循环再次检查条件,可以有效地处理虚假唤醒问题。