实验三 进程同步
一、 实验目的:
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
mutex = CreateMutex(NULL, FALSE, NULL);
第一个参数为互斥锁的安全属性,置为NULL表示不允许任何子进程继承该锁的句柄;第二个参数表示创建该锁的是否为初始拥有者,
置为FALSE表示不是初始拥有者;第三个参数表示锁的命名,NULL表示没有对其命名;若创建互斥锁成功,CreateMutex()返回互斥锁的句柄,否则返回NULL。 C. 创建信号量:
#include
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. 主函数: