MST

星途 面试题库

面试题:C语言中Linux条件变量虚假唤醒的常见场景及处理方法

在Linux环境下使用C语言的条件变量时,阐述虚假唤醒可能出现的常见场景,并说明如何通过代码来处理虚假唤醒,要求给出简单示例代码。
29.7万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

虚假唤醒常见场景

  1. 多线程竞争资源:当多个线程同时等待同一个条件变量时,系统可能会因为调度等原因,在条件未满足的情况下唤醒其中一个或多个线程。例如,在生产者 - 消费者模型中,多个消费者线程等待队列中有数据的条件变量,当生产者向队列中添加数据并唤醒等待的消费者线程时,可能会有多个消费者线程被唤醒,但此时队列中可能只有一条数据,多余被唤醒的消费者线程即为虚假唤醒。
  2. 信号干扰:Linux系统中,线程可能会收到一些信号,这些信号可能会导致条件变量的虚假唤醒。比如,一个线程正在等待条件变量,同时收到了一个异步信号,在处理信号后,线程可能会从等待条件变量的状态中被唤醒,即使条件并没有真正满足。

处理虚假唤醒的代码方式

使用循环检查条件变量的条件,确保唤醒后条件确实满足。当条件变量被唤醒时,不直接认为条件已经满足,而是再次检查条件。如果条件不满足,则继续等待。

示例代码

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;

void* thread_function(void* arg) {
    pthread_mutex_lock(&mutex);
    // 使用循环检查条件,防止虚假唤醒
    while (!ready) {
        printf("线程等待条件变量...\n");
        pthread_cond_wait(&cond, &mutex);
    }
    printf("线程被唤醒,条件已满足\n");
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main() {
    pthread_t tid;
    pthread_create(&tid, NULL, thread_function, NULL);

    sleep(2);  // 主线程睡眠2秒模拟其他工作

    pthread_mutex_lock(&mutex);
    ready = 1;
    printf("主线程设置条件为真,并唤醒等待的线程\n");
    pthread_cond_signal(&cond);
    pthread_mutex_unlock(&mutex);

    pthread_join(tid, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
    return 0;
}

在上述代码中,thread_function函数中的while (!ready)循环用于防止虚假唤醒。当pthread_cond_wait被唤醒时,会先检查ready条件,如果不满足则继续等待。主线程在设置ready1后,通过pthread_cond_signal唤醒等待的线程。