利用信号量解决生产者消费者问题 第2页
产品的计数器,计数器的初始值是可利用的资源数目(有界缓冲区的长度)。其次,它是确保产品的生产者和消费者之间动作同步的同步器。生产者要生产一个产品时,首先对资源信号量g_hFullSemaphore和互斥信号量g_hMutex进行P操作,申请资源。如果可以通过的话,就生产一个产品,并把产品送入缓冲区。然后对互斥信号量g_hMutex和资源信号量g_hEmptySemaphore进行V操作,释放资源。
消费者要消费一个产品时,首先对资源信号量g_hEmptySemaphore和互斥信号量g_hMutex进行P操作,申请资源。如果可以通过的话,就从缓冲区取出一个产品并消费掉。然后对互斥信号量g_hMutex和资源信号量g_hFullSemaphore进行V操作,释放资源。如果缓冲区中已经没有可用资源,就把申请资源的进程添加到等待队列的队尾。如果有一个资源被释放,在等待队列中的第一个进程被唤醒并取得这个资源的使用权。
图
P进程不能往“满”的缓冲区中放产品,设置信号量为s_empty;
Q进程不能从“空”的缓冲区中取产品,设置信号量s_full。
先设置信号量:s_empty初值为1, s_full初值为0
P: Q:
while (true) while (true)
{ {
生产一个产品; P(s_full);
P(s_empty); 从缓冲区取产品;
送产品到缓冲区; V(s_empty);
V(s_full); 消费产品;
}; };
以上算法可用下图来描述:若图片无法显示请联系QQ752018766
图
1.P原语操作的主要动作是:
(1)sem减1;
(2)若sem减1后仍大于或等于零,则进程继续执行;
(3)若sem减1后仍小于零,则该进程被阻塞后与该信号相对应的队列中,然后转进程调度。
P原语操作的功能框图如图1。
图1 P原语操作功能
2.V原语操作的主要动作是:若图片无法显示请联系QQ752018766
(1)sem加1;
(2)若相加结果大于零,则进程继续执行;
(3)若相加结果小于或等于零,则从该信号的等待队列中唤醒—等待进程,然后再返回原进程继续执行或转进程调度。
V原语操作的功能框图如图2。
图2 V原语操作功
const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度
unsigned short ProductID = 0; //产品号
unsigned short ConsumeID = 0; //将被消耗的产品号
unsigned short in = 0; //产品进缓冲区时的缓冲区下标
unsigned short out = 0; //产品出缓冲区时的缓冲区下标
int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列
bool g_continue = true; //控制程序结束
HANDLE g_hMutex; //用于线程间的互斥
HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待
HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待
DWORD WINAPI Producer(LPVOID); //生产者线程
DWORD WINAPI Consumer(LPVOID); //消费者线程
const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度
unsigned short ProductID = 0; //产品号
unsigned short ConsumeID = 0; //将被消耗的产品号
unsigned short in = 0; //产品进缓冲区时的缓冲区下标
unsigned short out = 0; //产品出缓冲区时的缓冲区下标
int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列
bool g_continue = true; //控制程序结束
HANDLE g_hMutex; //用于线程间的互斥
HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待
HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待
DWORD WINAPI Producer(LPVOID); //生产者线程
DWORD WINAPI Consumer(LPVOID); //消费者线程
用AND 型信号量解决生产者--消费者问题的算法说明如下:
semaphore mutex=1;
semaphore empty=n;
semaphore full=0;
item array[n];
int in=0;
int out=0;
producer()
{
while(ture)
{
produce an item in next_product;
Swaite(empty,mutex);
array[in]=next_product;
in=(in+1)%n;
Ssignal(mutex,full);
}
}
consumer()
{
while(ture)
{
上一页 [1] [2] [3] [4] [5] [6] 下一页