如何用管程实现生产者消费者问题?

文章目录

  • 管程的概念和结构
  • 管程主要特征
  • 管程语法
  • 用管程实现互斥
  • 用管程实现同步
    • 条件变量
    • 管程实现生产者消费者问题

管程的概念和结构

信号量操作系统提供的一种同步机制,优点是有效、灵活,缺点是容易出错、死锁。
管程高级语言提供的一种同步机制。包括Concurrent Pascal、Pascal-Plus、Moodula-2、Modula-3、Java等。

管程是一个软件模块,由三部分组成:一个或多个过程、一个初始化序列、本地数据。

管程结构
如何用管程实现生产者消费者问题?_第1张图片
shared data:存放需要互斥访问的数据;为了实现同步定义的同步变量;与同步变量相关的阻塞队列。
operations:存放管程定义的过程,这些过程可以访问shared data,也可以写wait和signal操作(与信号量中的不同,后面会介绍)。
initiallization code:初始化数据。
entry queue:等待进入管程的队列。

管程主要特征

只能由管程内的过程访问本地数据;
进程只能通过调用管程的过程进入管程;
每次只能有一个进程在管程内执行。

管程语法

monitor name	// monitor定义管程名字
{
     
	shared variable declarations;	// 定义共享数据
	procedure P1(...)				// 多个过程,用来被外部进程调用,访问共享数据
	{
     ...}
	procedure P2(...)
	{
     ...}
	procedure Pn(...)
	{
     ...}
	{
     initialization code}			// 共享数据的初始化代码
}

用管程实现互斥

因为管程在同一时刻只允许一个进程使用管程,所以管程提供互斥
只需把需要互斥访问的数据写成管程内部数据,把这些互斥的访问操作写成一个或多个过程,那么对这些数据的访问就实现了互斥。

用管程实现同步

条件变量

管程使用条件变量的方法支持同步。
条件变量在管程内部,只能由管程访问。
在条件变量C上可以有两种操作:C.wait()C.signal()
注意:管程的wait/signal操作和信号量的wait/signal操作是不同的。

C.wait()
直接阻塞调用管程的进程,直到有其他进程执行C.signal()为止。

C.signal()
若有因执行C.wait()操作而阻塞的进程,选择其中一个继续执行。
若没有因执行C.wait()操作而阻塞的进程,什么也不做。

只要执行C.signal()操作,就要立刻唤醒一个执行C.wait()操作被阻塞的进程。由于管程内部同一时刻只允许一个进程活跃,故当C.signal()不是进程中最后一条语句时,原来被阻塞的进程被唤醒,而自己还没有执行完,此时只好把自己阻塞掉。因此管程内还有一个紧急队列,用于存放因执行signal操作而把自己阻塞的进程。

管程实现生产者消费者问题

首先定义管程

montor boundedbuffer {
     
	char buffer[n];					// 缓冲区
	int nextin, nextout, count;		// count对产品计数
	condition notfull, notempty;	// 条件变量

	void append(char x);			// 将x插入缓冲区
	void take(char x);				// 从缓冲区取出x

	void init() {
     					// 初始化数据
		nextin = 0;
		nextout = 0;
		count = 0;
	}
}

void append(char x) {
     
	if (count == N)
		notfull.wait();				// 缓冲区满了,阻塞
	buffer[nextin] = x;
	nextin = (nextin + 1) % N;
	count++;
	notempty.signal();				// 有阻塞时唤醒,没有阻塞时丢弃
}

void take(char x) {
     
	if (count == 0)
		notempty.wait();			// 缓冲区为空,阻塞
	x = buffer[nextout];
	nextout = (nextout + 1) % N;
	count--;
	notfull.signal();				// 有阻塞时唤醒,没有阻塞时丢弃
}

实现

producer() {
     
	while(1) {
     
		produce(a);
		boundedbuffer.append(a);
	}
}

consumer() {
     
	while(1) {
     
		boundedbuffer.take(a);
		consume(a);
	}
}

你可能感兴趣的:(操作系统原理,操作系统,多线程)