MST

星途 面试题库

面试题:C语言Linux条件变量的虚假唤醒处理

在使用Linux C语言条件变量实现线程同步时,可能会遇到虚假唤醒的问题。请解释什么是虚假唤醒,为什么会出现,以及如何在代码中有效处理虚假唤醒,给出具体代码示例说明。
23.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

虚假唤醒的定义

虚假唤醒(spurious wakeup)是指在条件变量等待的线程,在没有其他线程调用 pthread_cond_signalpthread_cond_broadcast 来明确唤醒它的情况下,就从 pthread_cond_wait 调用中返回的现象。

虚假唤醒出现的原因

  1. 操作系统调度:操作系统的线程调度策略可能导致这种情况。在某些情况下,系统可能会错误地唤醒等待条件变量的线程,即使没有其他线程明确地发出唤醒信号。
  2. 信号处理:信号处理也可能与条件变量的等待机制相互干扰,从而导致虚假唤醒。

处理虚假唤醒的方法及代码示例

为了处理虚假唤醒,在从 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;
}

在上述代码中:

  1. 线程函数 thread_function:通过 while (shared_variable == 0) 循环来检查条件,确保只有当 shared_variable 确实为非零(条件满足)时才继续执行,从而处理了虚假唤醒的情况。
  2. 主线程:在设置 shared_variable 为 1 后,调用 pthread_cond_signal 唤醒等待的线程。

这样通过在 pthread_cond_wait 后使用循环再次检查条件,可以有效地处理虚假唤醒问题。