操作系统实验3进程同步报告

更新时间:2024-01-24 01:35:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验三 进程同步

一、 实验目的:

1. 了解进程和线程的同步方法,学会运用进程和线程同步方法来解决实际

问题;

2. 了解windows系统下Win32 API或Pthread信号量机制的使用方法;

二、 实验预备内容:

1. 对书上所说基于信号量的有限缓冲的生产者-消费者问题;

2. 对于信号量的概念有大概的了解,知道如何用信号量的wiat()和

signal()函数如何取消应用程序进入临界区的忙等;

三、 实验环境说明:

此实验在Win7(32位)CodeBlocks环境下实现,采用WinAPI的信号量机制。

四、 实验内容:

设计一个程序解决有限缓冲问题,其中的生产者与消费者进程如下图所示。在Bounded-Buffer Problem(6.6.1节)中使用了三个信号量:empty(记录有多少空位)、full(记录有多少满位)以及mutex(二进制信号量或互斥信号量,以保护对缓冲区插入与删除的操作)。对于本项目,empty和full将采用标准计数信号量,而mutex将采用二进制信号量。生产者与消费者作为独立线程,在empty、full、mutex的同步前提下,对缓冲区进行插入与删除。本项目可采用Pthread或Win32 API。(本实验采用Win32 API)

五、 程序设计说明:

1.

全局变量:

定义缓冲区数组及其环形队列表达方式,定义mutex、empty、full三个信号量。empty记录缓冲区有多少个空位;full记录缓冲区有多少个满位;mutex作为互斥信号量,保护对缓冲区插入或删除的操作。

具体定义如下:

定义生产者、消费者线程结构和包含的信息:(由于题目中没有要求,因此只定义了编号一个变量)

2.

缓冲区:

缓冲区是一个元数据类型为buffer_item(可通过typedef定义)的固定大小的数组,按环形队列处理。buffer_item的定义及缓冲区大小可保存在头文件中:

A.

insert_item():

先判断缓冲区是否已满,不满则向缓冲区中插入元素;

B.

remove_item()

先判断缓冲区是否为空,不空则从缓冲区中删除元素;

3.

生产者线程:

生产者线程交替执行如下两个阶段:睡眠一段随机事件,向缓冲中插入一个随机数。

4.

消费者线程:

消费者线程交替执行如下两个阶段:睡眠一段随机时间,醒后从缓冲

区内取出一项。

5.

Win32信号量机制: A. 创建线程(第四章):

B.

创建互斥锁:

#include HANDLE mutex;

mutex = CreateMutex(NULL, FALSE, NULL);

第一个参数为互斥锁的安全属性,置为NULL表示不允许任何子进程继承该锁的句柄;第二个参数表示创建该锁的是否为初始拥有者,

置为FALSE表示不是初始拥有者;第三个参数表示锁的命名,NULL表示没有对其命名;若创建互斥锁成功,CreateMutex()返回互斥锁的句柄,否则返回NULL。 C. 创建信号量:

#include HANDLE empty; HANDLE full;

empty=CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL); full=CreateSemaphore(NULL,0,BUFFER_SIZE + 1,NULL);

第一个参数表示安全属性;第二个参数表示信号量的初值;第三个参数表示信号量的最大值;第四个参数表示信号量的名称;若创建信号量成功,CreateSemaphore()返回指向信号量的句柄,否则返回NULL。

D. 获取信号量(相当于wait()函数):

WaitForSingleObject(Semaphore, INFINITE);

若信号量的值大于0,则处于触发态,可以为调用线程获取。否则由于定义了INFINITE,调用线程会进行无穷等待直到信号量为触发态。

E. 递增信号量(相当于signal()函数):

ReleaseSemaphore(Sem, 1, NULL); 第一个参数表示信号量的句柄;第二个参数表示信号量的递增大小;第三个参数表示信号量原值的指针;若成功,则ReleaseSemaphore()与ReleaseMutex()返回0,否则返回非0.

6. 主函数:

六、 运行结果:

缓冲区大小为5,手动输入生产者和消费者的线程数,观察运行结果。

1. 3个生产者线程,1个消费者线程,缓冲区的插入和删除操作都正常。

2.

3个生产者线程,2个消费者线程,缓冲区的插入和删除操作都正常。

3.

3个生产者线程,3个消费者线程,生产者生产出三个元素放入缓冲区,消费者消费掉这三个元素,再想要消费时候发现缓冲区内为空,因此输出错误提示信息。

4.

3个生产者线程,3个消费者线程,最初消费者想要消费,但是缓冲区为空,因此输出错误提示信息。生产者生产出2个元素放入缓冲区,消费者消费掉这2个元素,生产者再生产出1个元素放入缓冲区,消费者消费掉这1个元素,消费者再想要消费时候发现缓冲区内为空,

因此输出错误提示信息。

5.

3个生产者线程,3个消费者线程,最初消费者想要消费,但是缓冲区为空,因此输出错误提示信息。

6.

2个生产者线程,4个消费者线程,最初消费者想要消费,但是缓冲区为空,因此输出错误提示信息。生产者生产出1个元素放入缓冲区,消费者消费掉这1个元素,生产者再生产出2个元素放入缓冲区,消费者消费掉这2个元素,生产者接着生产出1个元素放入缓冲区,消费者消费掉这1个元素,消费者再想要消费时候发现缓冲区内为空,

因此输出错误提示信息。

7.

实验结果分析:

对比每次运行的结果发现都是随机的,并且消费者和生产者线程出现的先后顺序也是随机的。分析原因是由于给每一个消费者和生产者线程都睡眠了一段随机事件。本次测试对于线程数的设计包括两个线程数相等、消费者线程多于生产者以及生产者线程多于消费者,确保每一种情况都能正常运行,正常在缓冲区内进行插入和删除操作,若不满足条件则提示操作失败,报错。

七、 源代码:

1.

buffer.h

2.

pcProblem.c

八、 实验心得:

本次实验是在6.6.1节的Bounded-Buffer Problem的程序上解决有限缓冲问题。由于在书上基本做法和库函数的表示基本都给出了,没有给出的线程创建也给出了出处(第四章),所以在写代码的过程中还比较顺畅。但是因为开始并不是完全理解线程、信号量的使用方法,只是将书上给的伪代码复制下来,所以调试费了一些时间。但是也因此对于信号量创建和使用方法有了更深的理解,对于生产者-消费者问题的进程同步有了进一步的认识,有很大收获。

本文来源:https://www.bwwdw.com/article/l53o.html

Top