MST

星途 面试题库

面试题:C语言Linux线程同步之条件变量应用

在一个多线程的C程序中,假设存在生产者 - 消费者模型,生产者线程生产数据并放入共享缓冲区,消费者线程从共享缓冲区取出数据进行处理。请使用条件变量和互斥锁来实现该模型的线程同步,解释条件变量在这个场景中的工作原理,并给出完整的C代码实现。
46.5万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

条件变量在生产者 - 消费者模型中的工作原理

  1. 条件变量概述:条件变量是一种线程同步机制,用于线程间等待特定条件的发生。它通常与互斥锁配合使用,互斥锁用于保护共享资源,而条件变量用于线程间的协调。
  2. 生产者 - 消费者场景下的工作原理
    • 生产者线程
      • 首先获取互斥锁,以保护共享缓冲区。
      • 当共享缓冲区已满时,生产者线程调用pthread_cond_wait函数,该函数会自动释放它持有的互斥锁(避免死锁),然后生产者线程进入等待状态,直到其他线程(通常是消费者线程)发出条件变量的信号。
      • 当收到条件变量的信号(意味着共享缓冲区有空间了),生产者线程被唤醒,重新获取互斥锁,然后向共享缓冲区生产数据,最后释放互斥锁。
    • 消费者线程
      • 同样先获取互斥锁,保护共享缓冲区。
      • 当共享缓冲区为空时,消费者线程调用pthread_cond_wait,释放互斥锁并进入等待状态,直到生产者线程发出条件变量的信号。
      • 被唤醒后,消费者线程重新获取互斥锁,从共享缓冲区取出数据,最后释放互斥锁。

C代码实现

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

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t not_full = PTHREAD_COND_INITIALIZER;
pthread_cond_t not_empty = PTHREAD_COND_INITIALIZER;

void* producer(void* arg) {
    int i;
    for (i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while ((in + 1) % BUFFER_SIZE == out) {
            pthread_cond_wait(&not_full, &mutex);
        }
        buffer[in] = i;
        printf("Produced: %d\n", i);
        in = (in + 1) % BUFFER_SIZE;
        pthread_cond_signal(&not_empty);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

void* consumer(void* arg) {
    int i;
    for (i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (in == out) {
            pthread_cond_wait(&not_empty, &mutex);
        }
        int data = buffer[out];
        printf("Consumed: %d\n", data);
        out = (out + 1) % BUFFER_SIZE;
        pthread_cond_signal(&not_full);
        pthread_mutex_unlock(&mutex);
    }
    pthread_exit(NULL);
}

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(&not_full);
    pthread_cond_destroy(&not_empty);
    return 0;
}

这段代码实现了一个简单的生产者 - 消费者模型,使用了条件变量和互斥锁来确保线程安全和同步。producer函数模拟生产者线程,consumer函数模拟消费者线程。在main函数中创建并启动这两个线程,最后等待它们完成。在每个线程中,通过条件变量和互斥锁的配合,实现共享缓冲区的正确操作。