面试题答案
一键面试条件变量在生产者 - 消费者模型中的工作原理
- 条件变量概述:条件变量是一种线程同步机制,用于线程间等待特定条件的发生。它通常与互斥锁配合使用,互斥锁用于保护共享资源,而条件变量用于线程间的协调。
- 生产者 - 消费者场景下的工作原理:
- 生产者线程:
- 首先获取互斥锁,以保护共享缓冲区。
- 当共享缓冲区已满时,生产者线程调用
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(¬_full, &mutex);
}
buffer[in] = i;
printf("Produced: %d\n", i);
in = (in + 1) % BUFFER_SIZE;
pthread_cond_signal(¬_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(¬_empty, &mutex);
}
int data = buffer[out];
printf("Consumed: %d\n", data);
out = (out + 1) % BUFFER_SIZE;
pthread_cond_signal(¬_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(¬_full);
pthread_cond_destroy(¬_empty);
return 0;
}
这段代码实现了一个简单的生产者 - 消费者模型,使用了条件变量和互斥锁来确保线程安全和同步。producer
函数模拟生产者线程,consumer
函数模拟消费者线程。在main
函数中创建并启动这两个线程,最后等待它们完成。在每个线程中,通过条件变量和互斥锁的配合,实现共享缓冲区的正确操作。