Linux 系统应用编程——多线程经典问题(生产者-消费者)
“生产者——消费者”问题是Linux多线程编程中的经典问题,主要是利用信号量处理线程间的同步和互斥问题。
“生产者——消费者”问题描述如下:
有一个有限缓冲区(这里用有名管道实现 FIFO 式缓冲区)和两个线程:生产者和消费者,它们分别不停地把产品放入缓冲区中拿走产品。一个生产者在缓冲区满的时候必须等待,一个消费者在缓冲区空的时候也不IXUS等待。另外,因为缓冲区是临界资源,所以生产者和消费者之间必须互斥进行。它们之间的关系如下:
这里要求使用有名管道来模拟有限缓冲区,并用信号量来解决“生产者——消费者”问题中的同步和互斥问题。
1、信号量分析
这里使用3个信号量,其中两个信号量 avail 和 full 分别用于解决生产者和消费者线程之间的互斥问题。其中avail 表示缓冲区的空单元数,初始值为N;full 表示缓冲区非空单元数,初始值为 0 ; mutex 是互斥信号量 ,初始值为 1(当然也可以用互斥锁来实现互斥操作)。
2、画出流程图
3、编写代码
本实验的代码中缓冲区拥有3个单元,每个单元为5个字节。为了尽量体现每个信号量的意义,在程序中生产过程和消费过程是随机(采取0~5s 的随机事件间隔)进行的,而且生产者的速度比消费者的速度平均快两倍左右。生产者一次生产一个单元的产品(放入hello字符串),消费者一次消费一个单元的产品。
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <time.h>
- #include <fcntl.h>
- #include <semaphore.h>
- #include <sys/ipc.h>
- #include <errno.h>
- #define MYFIFO "myfifo"
- #define BUFFER_SIZE 3
- #define UNIT_SIZE 5
- #define RUN_TIME 30
- #define DELAY_TIME_LEVELS 5.0
- void *producer(void *arg);
- void *customer(void *arg);
- int fd;
- time_t end_time;
- sem_t mutex,full,avail;
- int main()
- {
- int ret;
- pthread_t thrd_prd_id,thrd_cst_id;
- srand(time(NULL));
- end_time = time(NULL) + RUN_TIME;
- /*创建有名管道*/
- if((mkfifo(MYFIFO,0644) < 0) && (errno != EEXIST))
- {
- perror("mkfifo error!");
- exit(-1);
- }
- /*打开管道*/
- fd = open(MYFIFO,O_RDWR);
- if(fd == -1)
- {
- perror("open fifo error");
- exit(-1);
- }
- /*初始化互斥信号量为1*/
- ret = sem_init(&mutex,0,1);
- /*初始化avail信号量为 N */
- ret += sem_init(&avail,0,BUFFER_SIZE);
- /*初始化full信号量为0*/
- ret += sem_init(&full,0,0);
- if(ret != 0)
- {
- perror("sem_init error");
- exit(-1);
- }
- /*创建两个线程*/
- ret = pthread_create(&thrd_prd_id,NULL,producer,NULL);
- if(ret != 0)
- {
- perror("producer pthread_create error");
- exit(-1);
- }
- ret = pthread_create(&thrd_cst_id,NULL,customer,NULL);
- if(ret != 0)
- {
- perror("customer pthread_create error");
- exit(-1);
- }
- pthread_join(thrd_prd_id,NULL);
- pthread_join(thrd_cst_id,NULL);
- close(fd);
- unlink(MYFIFO);
- return 0;
- }
- void *producer(void *arg) //生产者线程
- {
- int real_write;
- int delay_time;
- while(time(NULL) < end_time)
- {
- delay_time = (int)(rand() * DELAY_TIME_LEVELS/RAND_MAX/2.0) + 1;
- sleep(delay_time);
- /*P操作信号量avail和mutex*/
- sem_wait(&avail);
- sem_wait(&mutex);
- printf("\nproducer have delayed %d seconds\n",delay_time);
- /*生产者写入数据*/
- if((real_write = write(fd,"hello",UNIT_SIZE)) == -1)
- {
- if(errno == EAGAIN)
- {
- printf("The buffer is full,please wait for reading!\n");
- }
- }
- else
- {
- printf("producer writes %d bytes to the FIFO\n",real_write);
- printf("Now,the buffer left %d spaces!\n",avail);
- }
- /*V操作信号量full 和 mutex*/
- sem_post(&full);
- sem_post(&mutex);
- }
- pthread_exit(NULL);
- }
- void *customer(void *arg) //消费者线程
- {
- unsigned char read_buffer[UNIT_SIZE];
- int real_read;
- int delay_time;
- while(time(NULL) < end_time)
- {
- delay_time = (int)(rand() * DELAY_TIME_LEVELS/RAND_MAX/2.0) + 1;
- sleep(delay_time);
- sem_wait(&full); //P操作信号量full和mutex
- sem_wait(&mutex);
- memset(read_buffer,0,UNIT_SIZE);
- printf("\nCustomer have delayed %d seconds\n",delay_time);
- if((real_read = read(fd,read_buffer,UNIT_SIZE)) == -1)
- {
- if(errno == EAGAIN)
- {
- printf("The buffer is empty,please wait for writing!\n");
- }
- }
- else
- {
- printf("customer reads %d bytes from the FIFO\n",real_read);
- }
- sem_post(&avail); //V操作信号量 avail 和 mutex
- sem_post(&mutex);
- }
- pthread_exit(NULL);
- }
执行结果如下:
- fs@ubuntu:~/qiang/pthread$ ./cust_prod
- producer have delayed 2 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 2 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 2 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 3 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 3 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 1 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- Customer have delayed 1 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 3 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 1 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 2 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 1 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 2 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 1 spaces!
- Customer have delayed 3 seconds
- customer reads 5 bytes from the FIFO
- Customer have delayed 1 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 3 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- producer have delayed 1 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 1 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- Customer have delayed 1 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 3 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- Customer have delayed 2 seconds
- customer reads 5 bytes from the FIFO
- producer have delayed 2 seconds
- producer writes 5 bytes to the FIFO
- Now,the buffer left 2 spaces!
- fs@ubuntu:~/qiang/pthread$
Linux 系统应用编程——多线程经典问题(生产者-消费者)相关推荐
- Linux系统及编程期末试题,《LINUX系统及其编程》考试试题及答案.doc
<LINUX系统及其编程>考试试题及答案 <Linux系统及其编程>模拟练习参考答案 一.单项选择题 .Linux的根分区系统类型是 C . A. FAT16 B.FAT32 ...
- linux系统——Shell编程之变量解释
linux系统--Shell编程之变量解释 - Shell能做什么 自动化批量系统初始化程序 (update,软件安装,时区设置,安全策略-) 自动化批量软件部署程序 (LAMP,LNMP,Tomca ...
- linux系统/网络编程
经典数据: APUE:unix环境高级编程3版 linux系统编程手册 德 linux系统编程 oreily unix内核源码剖析 日 windows核心编程 linux系统开发模式: ssh远程登录 ...
- Linux 高性能服务器编程——多线程编程
问题聚焦: 在简单地介绍线程的基本知识之后,主要讨论三个方面的内容: 1 创建线程和结束线程: 2 读取和设置线程属性: 3 线程同步方式:POSIX信号量,互斥锁和条 ...
- Linux 系统应用编程——进程间通信(下)
在前面,我们学习了传统的进程间通信方式--无名管道(pipe).有名管道(fifo)和信号(signal). 下面我们来学习 System V IPC 对象: 1.共享内存(share memory ...
- Linux 系统应用编程——进程基础
一.Linux下多任务机制的介绍 Linux有一特性是多任务,多任务处理是指用户可以在同一时间内运行多个应用程序,每个正在执行的应用程序被称为一个任务. 多任务操作系统使用某种调度(shedule)策 ...
- linux系统io编程,Linux系统编程(1) —— 文件IO
本文主要对Linux系统中文件I/O的基本操作进行说明. 在Linux系统编程中,对文件进行处理的流程,通常是: 打开文件 读写文件 关闭文件 Linux内核对每一个进程维护一个打开的文件列表, 该文 ...
- Linux学习-Linux系统及编程基础笔记
useradd zhangsan passwd zhangsan visudo往/etc/sudoers文件中添加zhangsan #visudo 找到如下的行 root ALL=(ALL) ALL ...
- Linux 与 Python编程2021 经典函数实例 educoder实训
第1关:递归函数 - 汉诺塔的魅力 编程要求 本关的编程任务是补全src/step1/recursive.py文件的代码,实现相应的功能.具体要求如下: 定义一个函数fact(n),实现的功能是对输入 ...
最新文章
- Android资源命名规范
- python3教程-Python3教程
- C#操作config文件
- tigervnc环境搭建
- 中文乱码翻译器在线翻译_如何将芬兰语翻译成中文?这两种方法你得会
- node.js 模块_如何创建Node JS可重用模块
- pbrt源码中用全主元消去法求矩阵逆的实现
- 最优化理论与凸优化到底是干嘛的?
- CMD如何进入C:WINDOWS\SYSTEM32
- 自动驾驶-LQR工程实现(调研)
- 从大数据的角度看 房价一定会下跌
- 谈EBOM 、PBOM 、MBOM 在PDM中的统一
- coffeescript html5,CoffeeScript函数
- UE4虚幻引擎4多人联机基础知识和客户端服务器通信机制详解
- 怎么压缩gif图大小,gif压缩到微信表情
- Java的学习之路Day08
- Pytorch实现CT图像正投影(FP)与反投影(FBP)的模块
- 力扣题目归类,顺序刷题不再难
- 【Beta】Scrum Meeting 4
- Android异步消息处理机制之looper机制