linux下的生产者消费者问题
### Linux下的生产者消费者问题详解 #### 一、问题背景及意义 生产者消费者问题是多线程编程中的经典问题之一,通常用来模拟并发系统中资源有限的情况。在Linux环境下实现该问题,不仅可以帮助我们理解多线程编程的基本原理,还可以学习如何在Linux环境下使用信号量(Semaphore)和互斥锁(Mutex)来实现线程间的同步。 #### 二、代码分析与解释 本段代码通过使用C语言,在Linux环境下实现了生产者消费者问题的一个解决方案。接下来将对代码进行详细解析。 ##### 1. 定义宏变量 ```c #define N 2 // 消费者或者生产者的数目 #define M 10 // 缓冲数目 ``` 这里定义了两个宏变量`N`和`M`,分别表示生产者或消费者的数量以及缓冲区的大小。在这个例子中,有2个生产者和2个消费者,并且缓冲区的大小为10。 ##### 2. 全局变量声明 ```c int in = 0; // 生产者放置产品的位置 int out = 0; // 消费者取产品的位置 int buff[M] = {0}; // 缓冲初始化为0, 开始时没有产品 sem_t empty_sem; // 同步信号量, 当满了时阻止生产者放产品 sem_t full_sem; // 同步信号量, 当没产品时阻止消费者消费 pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲 int product_id = 0; //生产者id int prochase_id = 0; //消费者id ``` 这些全局变量用于管理整个程序的状态: - `in` 和 `out`:分别表示生产者放置产品的索引位置和消费者取走产品的索引位置。 - `buff[M]`:长度为`M`的数组,作为缓冲区存储产品。 - `empty_sem` 和 `full_sem`:两个信号量,分别用来控制何时可以生产产品和何时可以消费产品。 - `mutex`:一个互斥锁,用于保护对缓冲区的访问。 - `product_id` 和 `prochase_id`:分别为生产者和消费者的唯一标识符。 ##### 3. 函数定义 - **`print()`**:用于打印当前缓冲区的状态。 - **`product()`**:生产者线程的函数,负责向缓冲区中放入产品。 - **`prochase()`**:消费者线程的函数,负责从缓冲区中取出产品。 ##### 4. 生产者函数 `product()` ```c void *product() { int id = ++product_id; while (1) { sleep(1); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); in = in % M; printf("product%d in %d. like: \t", id, in); buff[in] = 1; print(); ++in; pthread_mutex_unlock(&mutex); sem_post(&full_sem); } } ``` 生产者线程的主要逻辑如下: - 通过`sem_wait(&empty_sem)`等待直到缓冲区有空闲空间。 - 使用`pthread_mutex_lock(&mutex)`获取互斥锁以确保对缓冲区的独占访问。 - 更新缓冲区中的数据。 - 释放互斥锁并通过`sem_post(&full_sem)`通知消费者线程缓冲区中有可用的产品。 ##### 5. 消费者函数 `prochase()` ```c void *prochase() { int id = ++prochase_id; while (1) { sleep(1); sem_wait(&full_sem); pthread_mutex_lock(&mutex); out = out % M; printf("prochase%d in %d. like: \t", id, out); buff[out] = 0; print(); ++out; pthread_mutex_unlock(&mutex); sem_post(&empty_sem); } } ``` 消费者线程的主要逻辑如下: - 通过`sem_wait(&full_sem)`等待直到缓冲区中有可用的产品。 - 使用`pthread_mutex_lock(&mutex)`获取互斥锁以确保对缓冲区的独占访问。 - 从缓冲区中取出产品并更新缓冲区状态。 - 释放互斥锁并通过`sem_post(&empty_sem)`通知生产者线程缓冲区中有空闲空间。 ##### 6. 主函数 `main()` ```c int main() { pthread_t tid1[N]; pthread_t tid2[N]; int i; int ret[N]; // 初始化信号量 int ini1 = sem_init(&empty_sem, 0, M); int ini2 = sem_init(&full_sem, 0, 0); if (ini1 && ini2 != 0) { printf("sem_init failed\n"); exit(1); } // 初始化互斥锁 int ini3 = pthread_mutex_init(&mutex, NULL); if (ini3 != 0) { printf("mutex_init failed\n"); exit(1); } // 创建生产者线程 for (i = 0; i < N; i++) { ret[i] = pthread_create(&tid1[i], NULL, product, (void *)(&i)); if (ret[i] != 0) { printf("product%d creation failed\n", i); exit(1); } } // 创建消费者线程 for (i = 0; i < N; i++) { ret[i] = pthread_create(&tid2[i], NULL, prochase, NULL); if (ret[i] != 0) { printf("prochase%d creation failed\n", i); exit(1); } } // 等待所有线程结束 for (i = 0; i < N; i++) { pthread_join(tid1[i], NULL); pthread_join(tid2[i], NULL); } exit(0); } ``` 主函数主要完成了以下任务: - 初始化信号量`empty_sem`和`full_sem`,其中`empty_sem`的初始值为`M`表示缓冲区全部为空,而`full_sem`的初始值为`0`表示缓冲区无任何产品。 - 初始化互斥锁`mutex`。 - 创建`N`个生产者线程和`N`个消费者线程。 - 等待所有线程结束。 #### 三、总结 通过以上代码的解析,我们可以看出,生产者消费者问题的解决关键在于正确使用信号量和互斥锁来保证线程间的同步与安全访问共享资源。本例中利用了信号量来限制生产者和消费者对缓冲区的操作频率,并使用互斥锁确保了线程安全地访问缓冲区,避免了竞态条件的发生。此外,通过调整`sleep()`函数中的参数,还可以进一步观察和调节生产者与消费者之间的速度差异,更好地理解两者之间的工作机制。
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define N 2 // 消费者或者生产者的数目
#define M 10 // 缓冲数目
int in = 0; // 生产者放置产品的位置
int out = 0; // 消费者取产品的位置
int buff[M] = {0}; // 缓冲初始化为0, 开始时没有产品
sem_t empty_sem; // 同步信号量, 当满了时阻止生产者放产品
sem_t full_sem; // 同步信号量, 当没产品时阻止消费者消费
pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲
int product_id = 0; //生产者id
int prochase_id = 0; //消费者id
/* 打印缓冲情况 */
void print()
{
int i;
for(i = 0; i < M; i++)
printf("%d ", buff[i]);
printf("\n");
}
/* 生产者方法 */
void *product()
{
int id = ++product_id;
while(1)
{
- 粉丝: 0
- 资源: 1
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 精选微信小程序源码:汤总便利小程序(门店店铺类)小程序(含源码+源码导入视频教程&文档教程,亲测可用)
- Excel弹窗“此工作簿包含到一个或多个可能不安全的外部源的链接” 场景范例
- C语言《基于ROS melodic,底盘控制器基于STM32的一个2D激光SLAM自主导小车》+项目源码+文档说明
- winform上位机图像采集控件.zip
- 工具变量全国供应链创新试点城市DID数据集(2007-2023年).xlsx
- SasAppsUserKeyBarUserTech_86_1.0.0.1.kop
- 项目售后服务及培训.docx
- 贪心算法介绍及入门案例
- 项目实施管理方案.docx
- 精选微信小程序源码:熊猫签证小程序(含源码+源码导入视频教程&文档教程,亲测可用)
- 1
- 2
前往页