管程 monitor的特点 管程是由若干过程、局部数据、初始化序列 组成的软件模块 局部数据变量只能被管程的过程访问 个进程通过调用某过程进入管程 只有一个进程能够进入,其他进程被挂起 互斥
管程monitor的特点 • 局部数据变量只能被管程的过程访问 • 一个进程通过调用某过程进入管程 • 只有一个进程能够进入,其他进程被挂起 互斥 管程是由若干过程、局部数据、初始化序列 组成的软件模块
利用条件变量实现同步 Wait(c) 挂起当前进程 管程变成可用状态 Signal(c) 执行等待队列中的头个进程 队列空则信号丢失
利用条件变量实现同步 • Cwait(c) – 挂起当前进程 – 管程变成可用状态 • Csignal(c) – 执行等待队列中的头个进程 – 队列空则信号丢失
管程的结构进入进程队列 条件C1 局部数据 wait(c1) 条件变量 条件cn 过程1 wait(cn) 紧急队列 过程k 初始化代码 signal 管程等待区管程 出口
管程的结构 局部数据 条件变量 过程1 过程k 初始化代码 … 条件c1 cwait(c1) cwait(cn) csignal 紧急队列 条件cn … 进入进程队列 管程等待区 管程 出口
Monitor boundedbuffer Char buffer[] 使用管程解决生 Int nextin, nextout 产者消费者问题 Int count Int notfull, notempty; Nextin=o: nextout=0: count=0 Void append(char x) Void take(char x if count==n wait(notfull); if count==0 wait(notempty) Buffer[nextinX; X= Buffer[nextout]; Nextin=(nextin+ 1 )%n Nextout=(nextout+1 )%n Count++ Count- Signal(notempty) Signal(notfull);
使用管程解决生 产者/消费者问题 Monitor boundedbuffer; Char buffer[n]; Int nextin,nextout; Int count; Int notfull,notempty; Void append(char x) {if count==n cwait(notfull); Buffer[nextin]=x; Nextin=(nextin+1)%n; Count++; Csignal(notempty); } Void take(char x) {if count==0 cwait(notempty); x= Buffer[nextout]; Nextout=(nextout+1)%n; Count--; Csignal(notfull); } Nextin=0;nextout=0;count=0;
使用管程解决 Void producer 生产者消费者 Char x 问题 While true Void consumer( [produce(x) Char x Append(x); While true ttake(x); Void main( consume (parbegin(producer, consumer);; Jy
使用管程解决 生产者/消费者 问题 Void producer() Char x {while true {produce (x); Append(x); }} Void consumer() Char x {while true {take(x); consume (x); }} Void main() {parbegin(producer,consumer);}
管程的问题 如果 signa不在进程未尾 需要两次进程切换 必须确保 signal之后立刻执行唤醒的进程 不能有新进程进入 Notify (x) 唤醒等待队列的头个进程 原进程继续执行
管程的问题 • 如果csignal不在进程末尾 – 需要两次进程切换 • 必须确保csignal之后立刻执行唤醒的进程 – 不能有新进程进入 • Cnotify(x) – 唤醒等待队列的头个进程 – 原进程继续执行
有界缓冲区管程代码 void append( char x) While count==n wait(notfull) Buffer[nestin]=X; Nextin=(nextin+1 )%n; Count++, void take(char x) Notify(notempty):) iwhile count==0 wait(notempt X= Butfernextout] Nextout-= nextout +1)%n Count-- Notify(notfull)
有界缓冲区管程代码 void append(char x) {while count==n cwait(notfull); Buffer[nextin] =x; Nextin=(nextin+1)%n; Count++; Cnotify(notempty); } void take(char x) {while count==0 cwait(notempty); x = Buffer[nextout]; Nextout=(nextout+1)%n; Count--; Cnotify(notfull); }
Notify的优点 唤醒进程执行前再次测试-whie 给每个条件变量设置监视计时器 Broadcast原语 不知道该唤醒几个进程 不知道该唤醒哪个进程 识别错误发出的信号
Cnotify的优点 • 唤醒进程执行前再次测试-while • 给每个条件变量设置监视计时器 • Cbroadcast原语 – 不知道该唤醒几个进程 – 不知道该唤醒哪个进程 • 识别错误发出的信号
消息传递 send(目标,消息) Receive(来源,消息) Send(distination, message Receive(source, message
消息传递 Send(目标,消息) Receive(来源,消息) Send(distination,message) Receive(source,message)