1、武 汉 理 工 大 学 华 夏 学 院课 程 设 计 报 告 书课程名称: 操作系统原理 题 目:用多线程同步方法解决生产者消费者问题 系 名: 信息工程系 专业班级: 软件 1091 班 姓 名: 千里锋行 学 号: 10212809121 指导教师: 赵传斌 苏永红 2011 年 12 月 21 日武汉理工大学华夏学院操作系统课程设计说明书课程设计任务书学生姓名: 千里锋行 专业班级: 软件 1091 指导教师: 苏永红 工作单位: 设计题目:用多线程同步方法解决生产者消费者问题初始条件:1 操作系统:Linux2 程序设计语言:C 语言3 有界缓冲区内设有 20 个存储单元,其初值为 0
2、。放入取出的数据项按增序设定为120 这 20 个整型数。要求完成的主要任务:主要任务:通过研究 Linux 的线程机制和信号量实现生产者消费者问题的并发控制。有界缓冲区内设有 20 个存储单元,放入取出的数据项设定为 120 这 20 个整型数。(1) 每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者消费者线程的标识符。(2) 生产者和消费者各有两个以上。(3) 多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。提示:(1)有界缓冲区/ 连续存储区可用数组实现。(2) 编译命令可用:gcc -lpthread -o 目标文件名 源文件名(
3、3) 多线程编程方法参见电子文档。设计报告撰写格式要求:1 设计题目与要求 2 设计思想3 系统结构 4 数据结构的说明和模块的算法流程图5 使用说明书(即用户手册):内容包含如何登录、退出、读、写等操作说明6 运行结果和结果分析(其中包括实验的检查结果、程序的运行情况)7 自我评价与总结8 附录:程序清单,注意加注释(包括关键字、方法、变量等),在每个模块前加注释;时间安排 12 月 19 日 布置课程设计任务;分配题目后,查阅资料、 准备程序;12 月 19 12 月 21 日上机调试程序、书写课程设计报告;12 月 22 日 提交课程设计报告及相关文档。指 导 教 师 签 字: 2011
4、 年 12 月 17 日系 主 任 签 字: 2011 年 12 月 18 日武汉理工大学华夏学院操作系统课程设计说明书一 设计题目与要求1 设计目的通过研究 Linux 的线程机制和信号量实现生产者消费者问题(Producer-Consumer Problem)的并发控制。2 设计要求1)为每个生产者消费者产生一个线程,设计正确的同步算法2)每个生产者/消费者对该存储区进行操作后,即时显示该存储区的全部内容、当前指针位置和生产者/消费者线程的自定义标识符。3)生产者和消费者各有两个以上。4)多个生产者/消费者之间须共享对存储区进行操作的函数代码。二设计思想本次课设涉及到同步信号量和互斥信号量
5、的应用,在这里我用线程的同步和互斥来实现。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。在本问题中,共需要一个 Mutex 和两个 Semaphore,其中 Mutex 是来用锁定临界区的,以解决对共享数据 buffer 的互斥访问问题(无论是对生成者还是对消费者);我们共需要两个 Semaphore,
6、这是因为在本问题中共有两个稀缺资源.第一种是“非空“这种资源,是在消费者之间进行竞争的;第二种是“非满“这种资源,是在生产者之间进行竞争的.所以,一般来说,需要锁定临界区,就需要 Mutex;有几种稀缺资源就需要几个 Semaphore.稀缺资源不一定是指被共享的资源,很多时候是指线程会被阻塞的条件(除了要进临界区被阻塞外).在生产者消费者问题中,消费者会在缓冲区为空时被阻塞,所以“非空“是一种稀武汉理工大学华夏学院操作系统课程设计说明书缺资源。需要设置一个信号量 consumer_semaphore,初值设为 0,生产者会在缓冲区为满时被阻塞,所以“非满“也是一种稀缺资源.需要设置一个信号量
7、producer_semaphore,初值设为 buffer 的大小 MAX_BUFFER。三系统结构四数据结构的说明和模块的算法流程图生产者消费者问题模拟生产者线程 消费者线程生产者方法 打印缓冲情况 打印缓冲情况消费者方法开始生产者 id 加 1等待 empty_sem 信号量加锁缓冲区位置加 1解锁锁设置 full_sem 信号量开始消费者 id 加 1等待 full_sem 信号量加锁缓冲区位置加 1解锁锁设置 empty_sem 信号量生产者方法: 消费者方法:武汉理工大学华夏学院操作系统课程设计说明书五使用说明书1.宏的意义:N:消费者或者生产者的数目M:缓冲区的数目2.程序的运行
8、a打开 linux 的终端;b编译程序,输入命令gcc o dyb dyb.c pthread ;./dyb3.显示结果程序运行后不需要接受用户输入,直接显示运行结果。六运行结果和结果分析djsofteem $ lsdyb.c 公共的 模板 视频 图片 文档 下载 音乐 桌面djsofteem $ gcc -o dyb dyb.c -pthreaddjsofteem $ ./dybproducer1 in 0: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 customer1 in 0: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9、0 0 producer2 in 1: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 customer2 in 1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 2: 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 customer1 in 2: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 3: 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 customer2 in 3:
10、0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 4: 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 customer1 in 4: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 5: 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 customer2 in 5: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 6: 0 0 0 0 0 0 1 0 0 0
11、0 0 0 0 0 0 0 0 0 0 customer1 in 6: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 7: 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 customer2 in 7: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 8: 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 customer1 in 8: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
12、producer2 in 9: 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 customer2 in 9: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 10: 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 customer1 in 10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 11: 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 武汉理工大学华夏学院操作系统课程设
13、计说明书customer2 in 11: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 12: 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 customer1 in 12: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 13: 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 customer2 in 13: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 i
14、n 14: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 customer1 in 14: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 15: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 customer2 in 15: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 16: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 customer1 in 16: 0 0 0 0 0
15、 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 17: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 customer2 in 17: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer1 in 18: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 customer1 in 18: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 producer2 in 19: 0 0 0 0 0 0 0 0 0 0 0 0
16、0 0 0 0 0 0 0 1 customer2 in 19: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 对于此程序,有 20 个缓冲区,定义了两个生产者和两个消费者,生产者和消费者是模拟的现实中的生产与消费的关系,生产者生产产品时占用一个线程 ,消费者取一个产品时启用一个线程,生产产品和消费产品是利用锁来实现的。 但是最后还是有问题没能解决好,就是生产一个消费一个,缓冲区就没有利用好。七自我评价与总结本次课程设计,听了邓君老师几天的讲解,见识到了他的年轻有为,也让自己对 IT 行业有了更深的向往。同时也加深了一些对多线程编程方法的理解,和使用信号量同步
17、进/线程的技巧。上课时看邓老师演示在 linux 下编写一个多人聊天的小程序,我在下面也跟住做。几次遇到了问题,老师都及时耐心的给我解决。最后我也跟着老师敲代码,虽然只是敲代码,不是自己的思想写出来的,但是万事开头难,我觉得只要我动手了,就成功了一半。在跟着老师做的过程中,我体会到了自己的不足,很多地方都不懂,但是我觉得在这个阶段对一些比较深的东西也不一定要处处都弄懂,有时候子要自己跟着做,会用,久而久之也会随着经验的加深而慢慢弄懂,这虽然是一种不求甚解的态度,但在初级编程中往往是很有用的。本次课程设计的程序更具要求定义了 20 个缓冲区,基本上能顺利解决生产者消费者问题,但也存在很多不足之处
18、。因为程序都是根据别人的来的,所以往往想加入自己的想法,比如随机函数解决随机的问题时遇到障碍,最后由于出现的错误太多,时间不够,所以只得放弃,只能在武汉理工大学华夏学院操作系统课程设计说明书一些小的边边角角上稍加改动,试着去体会这个程序的思想。设计过程中质疑(或答辩)记载:1.谈谈你对多线程的理解。答:在一个程序中,独立运行的程序片断叫作“线程”(Thread) ,利用它编程的概念就叫作“多线程处理”。多 线 程 是 为 了 同 步 完 成 多 项 任 务 , 不 是 为 了 提 高 运 行 效 率 , 而 是 为 了 提高 资 源 使 用 效 率 来 提 高 系 统 的 效 率 。 线 程
19、是 在 同 一 时 间 需 要 完 成 多 项 任 务 的 时 候 实 现 的 。2. 此程序的不足之处答:定义了 20 个缓冲区,但是每次只利用到 1 个缓冲区,造成了资源的浪费,没有起到随机的作用。我曾尝试用随机函数去解决,但是没能成功。指导教师评语:签名:年 月 日武汉理工大学华夏学院操作系统课程设计说明书七附录程序清单:#include #include #include #include #include #define N 2 / 消费者或者生产者的数目#define M 20 / 缓冲数目int in = 0; / 生产者放置产品的位置int out = 0; / 消费者取产品的
20、位置int buffM = 0; / 缓冲初始化为 0, 开始时没有产品sem_t empty_sem; / 同步信号量, 当满了时阻止生产者放产品sem_t full_sem; / 同步信号量, 当没产品时阻止消费者消费pthread_mutex_t mutex; / 互斥信号量, 一次只有一个线程访问缓冲int product_id = 0; /生产者 idint prochase_id = 0; /消费者 id/* 打印缓冲情况 */void print()int i;for(i = 0; i M; i+)printf(“%d “, buffi);printf(“n“);/* 生产者方法
21、 */ void *product()int id = +product_id;while(1)/ 用 sleep 的数量可以调节生产和消费的速度,便于观察sleep(1);/sleep(1);武汉理工大学华夏学院操作系统课程设计说明书sem_wait(pthread_mutex_lock(in = in % M;printf(“producer%d in %d: “, id, in);buffin = 1; print(); +in;pthread_mutex_unlock(sem_post( /* 消费者方法 */void *prochase()int id = +prochase_id;
22、while(1)/ 用 sleep 的数量可以调节生产和消费的速度,便于观察sleep(1);/sleep(1);sem_wait(pthread_mutex_lock(out = out % M;printf(“customer%d in %d: “, id, out);buffout = 0;print();+out;pthread_mutex_unlock(sem_post(int main()pthread_t id1N;pthread_t id2N;int i;int retN;/ 初始化同步信号量武汉理工大学华夏学院操作系统课程设计说明书int ini1 = sem_init( i
23、nt ini2 = sem_init( if(ini1 exit(1); /初始化互斥信号量 int ini3 = pthread_mutex_init(if(ini3 != 0)printf(“mutex init failed n“);exit(1); / 创建 N 个生产者线程for(i = 0; i N; i+)reti = pthread_create(if(reti != 0)printf(“product%d creation failed n“, i);exit(1);/创建 N 个消费者线程for(i = 0; i N; i+)reti = pthread_create(if(reti != 0)printf(“prochase%d creation failed n“, i);exit(1);/销毁线程for(i = 0; i N; i+)pthread_join(id1i,NULL);pthread_join(id2i,NULL);exit(0);