MST

星途 面试题库

面试题:C语言Linux条件变量的同步优化

在多线程环境下,使用C语言的Linux条件变量实现一个生产者 - 消费者模型。要求考虑如何避免虚假唤醒问题,并对条件变量和互斥锁的同步机制进行优化,以提高整体效率。请给出详细的代码实现及关键步骤的解释。
48.4万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

以下是使用C语言在Linux下通过条件变量实现生产者 - 消费者模型的代码示例,同时考虑了避免虚假唤醒问题,并对同步机制进行了优化:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.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 = 1;
    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);
        item++;
        sleep(1);
    }
    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);
        sleep(1);
    }
    return NULL;
}

关键步骤解释:

  1. 缓冲区及变量定义
    • buffer 数组作为共享缓冲区,大小为 BUFFER_SIZE
    • inout 分别是生产者和消费者的索引。
    • count 记录缓冲区中当前的元素数量。
  2. 同步变量初始化
    • pthread_mutex_t mutex 用于保护共享资源,避免竞态条件。
    • pthread_cond_t not_full 条件变量用于通知生产者缓冲区未满。
    • pthread_cond_t not_empty 条件变量用于通知消费者缓冲区非空。
  3. 生产者函数
    • pthread_mutex_lock(&mutex) 加锁,保护共享资源。
    • while (count == BUFFER_SIZE) 循环检查缓冲区是否已满,避免虚假唤醒。若满则调用 pthread_cond_wait(&not_full, &mutex) 等待,同时释放锁。
    • 生产数据并更新 incount
    • pthread_cond_signal(&not_empty) 通知消费者缓冲区有数据。
    • pthread_mutex_unlock(&mutex) 解锁。
  4. 消费者函数
    • pthread_mutex_lock(&mutex) 加锁,保护共享资源。
    • while (count == 0) 循环检查缓冲区是否为空,避免虚假唤醒。若空则调用 pthread_cond_wait(&not_empty, &mutex) 等待,同时释放锁。
    • 消费数据并更新 outcount
    • pthread_cond_signal(&not_full) 通知生产者缓冲区有空间。
    • pthread_mutex_unlock(&mutex) 解锁。

这样可以有效地实现一个在多线程环境下的生产者 - 消费者模型,并通过避免虚假唤醒和合理的同步机制优化提高整体效率。在实际使用中,可以根据具体需求进一步调整和扩展代码。