Linux下生产者-消费者模型

Linux下生产者-消费者模型 摘要本文记录了在 Ubuntu 虚拟机环境下使用 C 语言和 POSIX 线程库解决经典“生产者-消费者”问题的完整代码与编译步骤。核心在于利用信号量控制缓冲区同步利用互斥锁保证数据安全。1. 核心思路互斥锁 (mutex)保证同一时刻只有一个线程操作缓冲区。信号量 (empty,full)empty初始为缓冲区大小 $M$表示还能放多少数据。full初始为 0表示已经有多少数据可取。2. 完整代码 (producer_consumer.c)#include stdio.h #include stdlib.h #include unistd.h #include pthread.h #include semaphore.h #define BUFFER_SIZE 5 // 缓冲区大小 #define PRODUCER_COUNT 2 #define CONSUMER_COUNT 2 int buffer[BUFFER_SIZE]; int in 0, out 0; // 定义同步工具 sem_t empty_sem; sem_t full_sem; pthread_mutex_t mutex; void *producer(void *arg) { int id *(int *)arg; while(1) { sleep(1); // 模拟生产耗时 sem_wait(empty_sem); // P(empty): 等待空位 pthread_mutex_lock(mutex); // 加锁 // --- 临界区放入数据 --- buffer[in] 1; printf([生产者 %d] 放入数据 - 位置: %d\n, id, in); in (in 1) % BUFFER_SIZE; pthread_mutex_unlock(mutex); // 解锁 sem_post(full_sem); // V(full): 增加满位 } } void *consumer(void *arg) { int id *(int *)arg; while(1) { sleep(2); // 模拟消费耗时 sem_wait(full_sem); // P(full): 等待数据 pthread_mutex_lock(mutex); // 加锁 // --- 临界区取出数据 --- int data buffer[out]; printf([消费者 %d] 取出数据 - 位置: %d\n, id, out); out (out 1) % BUFFER_SIZE; pthread_mutex_unlock(mutex); // 解锁 sem_post(empty_sem); // V(empty): 增加空位 } } int main() { pthread_t prod[PRODUCER_COUNT], cons[CONSUMER_COUNT]; int p_ids[PRODUCER_COUNT], c_ids[CONSUMER_COUNT]; // 初始化 sem_init(empty_sem, 0, BUFFER_SIZE); sem_init(full_sem, 0, 0); pthread_mutex_init(mutex, NULL); // 创建线程 for(int i0; iPRODUCER_COUNT; i) { p_ids[i] i1; pthread_create(prod[i], NULL, producer, p_ids[i]); } for(int i0; iCONSUMER_COUNT; i) { c_ids[i] i1; pthread_create(cons[i], NULL, consumer, c_ids[i]); } // 等待结束 (此处为死循环演示实际需CtrlC退出) for(int i0; iPRODUCER_COUNT; i) pthread_join(prod[i], NULL); for(int i0; iCONSUMER_COUNT; i) pthread_join(cons[i], NULL); return 0; }3. 编译与运行步骤在你的 Ubuntu 终端中执行以下命令编译注意必须链接pthread库gcc producer_consumer.c -o pc_demo -lpthread运行./pc_demo4. 实验总结通过观察控制台输出可以看到生产者和消费者交替进行且不会出现“缓冲区溢出”或“从空缓冲区读取”的错误验证了 PV 操作的有效性。