MST

星途 面试题库

面试题:C语言中Linux多线程服务器模型条件变量与互斥锁的协作

在Linux C语言多线程服务器开发中,条件变量常与互斥锁配合使用来实现更复杂的线程同步。请详细解释条件变量与互斥锁协作的原理,以及在生产者 - 消费者模型场景下,如何利用它们保证数据的正确处理和线程间的高效协作,给出相应的核心代码逻辑。
17.1万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

条件变量与互斥锁协作原理

  1. 互斥锁(Mutex)
    • 互斥锁用于保护共享资源,确保同一时间只有一个线程能够访问共享资源,避免数据竞争。它是一种二元信号量,只有两种状态:锁定(locked)和解锁(unlocked)。
    • 当一个线程获取到互斥锁(将其状态设为锁定),其他线程试图获取该互斥锁时会被阻塞,直到持有锁的线程释放锁(将其状态设为解锁)。
  2. 条件变量(Condition Variable)
    • 条件变量用于线程间的同步,它允许线程等待某个条件满足。条件变量本身并不保护共享资源,需要与互斥锁配合使用。
    • 一个线程可以在条件变量上等待,同时释放与之关联的互斥锁,进入睡眠状态。当另一个线程改变了共享资源的状态,使得等待的条件满足时,它可以唤醒在该条件变量上等待的线程。被唤醒的线程会重新获取互斥锁,然后继续执行。

生产者 - 消费者模型下的应用

  1. 场景描述
    • 生产者线程不断生成数据并放入共享缓冲区,消费者线程从共享缓冲区取出数据进行处理。共享缓冲区的大小有限,需要避免生产者在缓冲区满时继续写入,以及消费者在缓冲区空时读取。
  2. 核心代码逻辑(以Linux pthread库为例)
#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 i;
    for (i = 0; i < 10; i++) {
        pthread_mutex_lock(&mutex);
        while (count == BUFFER_SIZE) {
            pthread_cond_wait(&not_full, &mutex);
        }
        buffer[in] = i;
        printf("Produced: %d\n", buffer[in]);
        in = (in + 1) % BUFFER_SIZE;
        count++;
        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 (count == 0) {
            pthread_cond_wait(&not_empty, &mutex);
        }
        int data = buffer[out];
        printf("Consumed: %d\n", data);
        out = (out + 1) % BUFFER_SIZE;
        count--;
        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;
}

在上述代码中:

  • 互斥锁 mutex:保护共享缓冲区 buffer 以及相关变量 inoutcount,确保在访问这些共享资源时的互斥性。
  • 条件变量 not_full:当缓冲区满时(count == BUFFER_SIZE),生产者线程通过 pthread_cond_wait 等待该条件变量,同时释放互斥锁 mutex。当消费者从缓冲区取出数据后,通过 pthread_cond_signal 唤醒等待在 not_full 上的生产者线程。
  • 条件变量 not_empty:当缓冲区空时(count == 0),消费者线程通过 pthread_cond_wait 等待该条件变量,同时释放互斥锁 mutex。当生产者向缓冲区写入数据后,通过 pthread_cond_signal 唤醒等待在 not_empty 上的消费者线程。