MST

星途 面试题库

面试题:C语言Linux多线程条件变量的应用

在一个生产者 - 消费者模型的多线程程序中,使用C语言结合Linux多线程库,如何利用条件变量来实现线程间的高效同步?请详细描述设计思路并给出核心代码片段,同时说明条件变量与互斥锁配合使用时需要注意的要点。
23.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 初始化:初始化互斥锁和条件变量,为线程间同步做准备。
  2. 生产者线程:生产数据,获取互斥锁,将数据放入共享缓冲区,然后通知等待在条件变量上的消费者线程。
  3. 消费者线程:获取互斥锁,检查共享缓冲区是否有数据,若没有则等待在条件变量上,有数据则取出数据并处理。
  4. 清理:程序结束时,销毁互斥锁和条件变量。

核心代码片段

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

#define BUFFER_SIZE 10
int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

// 生产者线程函数
void *producer(void *arg) {
    int item = 0;
    while (1) {
        pthread_mutex_lock(&mutex);
        while ((in + 1) % BUFFER_SIZE == out) {
            // 缓冲区满,等待
            pthread_cond_wait(&cond, &mutex);
        }
        buffer[in] = item++;
        printf("Produced: %d\n", buffer[in]);
        in = (in + 1) % BUFFER_SIZE;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

// 消费者线程函数
void *consumer(void *arg) {
    while (1) {
        pthread_mutex_lock(&mutex);
        while (in == out) {
            // 缓冲区空,等待
            pthread_cond_wait(&cond, &mutex);
        }
        int item = buffer[out];
        printf("Consumed: %d\n", item);
        out = (out + 1) % BUFFER_SIZE;
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

main 函数中创建生产者和消费者线程:

int main() {
    pthread_t producer_thread, consumer_thread;

    pthread_create(&producer_thread, NULL, producer, NULL);
    pthread_create(&consumer_thread, NULL, consumer, NULL);

    pthread_join(producer_thread, NULL);
    pthread_join(consumer_thread, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

条件变量与互斥锁配合使用要点

  1. 先加锁:在调用 pthread_cond_wait 之前必须先获取互斥锁,因为 pthread_cond_wait 函数会自动释放互斥锁并使线程等待,当被唤醒时又会重新获取该互斥锁。
  2. 检查条件:在等待条件变量时,应该使用循环检查条件,而不是单次检查,以防止虚假唤醒(spurious wakeup)。虚假唤醒是指线程可能在没有调用 pthread_cond_signalpthread_cond_broadcast 的情况下被唤醒。
  3. 信号发送:在条件满足时,调用 pthread_cond_signalpthread_cond_broadcast 通知等待在条件变量上的线程。pthread_cond_signal 通常用于唤醒单个等待线程,pthread_cond_broadcast 用于唤醒所有等待线程。在调用这些函数前,也需要持有互斥锁。
  4. 锁的范围:确保互斥锁保护的是与条件变量相关的共享资源,且在使用条件变量的整个过程中,对共享资源的访问都在互斥锁的保护下。
  5. 清理:程序结束时,务必正确销毁互斥锁和条件变量,避免资源泄漏。