MST
星途 面试题库

面试题:进程管理之条件变量在复杂通信场景的应用

假设存在一个生产者 - 消费者模型,多个生产者进程向共享缓冲区写入数据,多个消费者进程从共享缓冲区读取数据。在这个模型中,使用条件变量实现进程间通信,要求考虑缓冲区满、缓冲区空以及数据一致性等问题,描述你的设计思路并给出关键代码片段。
36.4万 热度难度
操作系统进程管理

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 共享缓冲区:使用数组或链表来实现共享缓冲区,记录缓冲区的状态(如已占用的位置、总大小等)。
  2. 条件变量
    • 一个条件变量用于表示缓冲区为空的情况,当缓冲区为空时,消费者进程等待这个条件变量。
    • 另一个条件变量用于表示缓冲区为满的情况,当缓冲区为满时,生产者进程等待这个条件变量。
  3. 互斥锁:为了保证对共享缓冲区的访问是线程安全的,需要使用互斥锁来保护共享资源。在访问共享缓冲区之前加锁,访问完之后解锁。
  4. 数据一致性:通过互斥锁来确保在同一时间只有一个进程可以访问共享缓冲区,避免数据竞争。同时,使用条件变量来保证生产者和消费者之间的同步,确保数据的正确读写。

关键代码片段(以C语言为例,基于POSIX线程库)

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

#define BUFFER_SIZE 5
int buffer[BUFFER_SIZE];
int in = 0;
int out = 0;
int count = 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 item = *((int*)arg);
    while (1) {
        pthread_mutex_lock(&mutex);
        while (count == BUFFER_SIZE) {
            pthread_cond_wait(&not_full, &mutex);
        }
        buffer[in] = item;
        printf("Produced: %d\n", item);
        in = (in + 1) % BUFFER_SIZE;
        count++;
        pthread_cond_signal(&not_empty);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

// 消费者函数
void* consumer(void* arg) {
    while (1) {
        pthread_mutex_lock(&mutex);
        while (count == 0) {
            pthread_cond_wait(&not_empty, &mutex);
        }
        int item = buffer[out];
        printf("Consumed: %d\n", item);
        out = (out + 1) % BUFFER_SIZE;
        count--;
        pthread_cond_signal(&not_full);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

在主函数中可以创建生产者和消费者线程并传入相应参数,然后等待线程结束,释放资源:

int main() {
    pthread_t producer_thread, consumer_thread;
    int producer_item = 1;
    int consumer_item = 1;

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

    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;
}