操作系统清华大学版笔记(十) 信号量、管程、条件互斥、经典同步问题(读者写者、哲学家问题)

10-1 信号量 Semaphore

一个整型int(sem),可进行两个原子操作

P() sem–,如果sem<0,等待,否则继续,类似lock_acquire 

V() sem++,如果sem<=0,说明当前有等着的,唤醒挂在信号量上的进程,可以是一个,可以是多个

Dijkstra在20实际60年代提出,P,V都是荷兰语,在早期操作系统中,P,V是主要的同步原语。

类似信号灯



特征 
信号量是整数,有符号,一般初始是>0的数,一旦小于0就不能继续,要挂在信号量上,其他进程做V操作才能唤醒,具体唤醒哪个取决于具体的算法,如常用FIFO先来先服务,较为公平; 

信号量是被保护的变量,初始化完成后只能通过P() V()这两个原子操作改变值,P操作会阻塞,V不会

10-2 如何使用信号量

两种类型: 
二进制信号量:约等于锁,取值0 or 1 
general counting一般/技术信号量:任何非负值 
可以用在两个方面,互斥或者条件同步(调度约束—–一个线程等待另一个线程的事情发生)

用二进制信号量实现锁的互斥

mutex= new semaphore(0)
mutex->P();
…Critical section…
mutex->V();

实现调度约束

condition=new semaphore(0);

for thread A condition->P(); 开始等待for thread B

condition->V(); 发出信号唤醒A ,B在V操作之前的语句执行完后才能执行A的P之后的语句----同步

条件同步 


正确性要求:可以多个生产者访问Buffer写数据,但写的时候消费者不能有操作(互斥),缓冲区空,

消费者必须等待生产者,缓冲区满,生产者必须等待消费者(调度/同步约束)。

每个约束用一个单独的信号量,设置三个 

二进制信号量互斥(1/0),一般信号量fullbuffers,一般信号量emptybuffer

初始化

Class BoundedBuffer{
Mutex = new semaphore(1);
fullBuffers = new semaphore(0);
emptyBuffers = new semaphore(n); //当前生产者可以往里面放多少个数据
}
BoundedBuffer::Deposit(c){
emptyBuffer->P();           //n个生产者都可以进入直到empty<0被阻塞,不能先锁再emptybuffer--, 不然会在Buffers满的时候死锁
mutex->P(); Add c to the buffer; mutex->V();
fullBuffers->V();               //初始是0,只有先V()不然消费者不能取}
BoundedBuffer::Remove(c){ 
fullBuffers->P();           //  初始是0时会被挂起
mutex->P();Remove c from buffer; mutex->V();
emptyBuffers->V();
}
P&V可以换顺序吗?可以。

10-3 信号量实现细节

class Semaphore{
int sem;
Waitqueue q;}

Semaphore::P(){
sem--;
if(sem<0){Add this thread t to q;   block(p);}
}

Semaphore::V(){
Sem++;
If(sem<=0){
Remove a thread t from q;   wakeup(t);}
}

存在问题:

  • 信号量的双用途,互斥和条件同步,等待条件是独立的互斥。和LOCK有区别,
  • LOCK是通过忙等/等待队列实现sleep,信号量是等待队列。
  • 开发容易犯错,比较困难
  • 不能够处理死锁

10-4 管程 条件变量


管程monitor 包含了一系列的共享变量,以及针对这些变量的操作的函数的组合/模块 

包含了:一个锁,指定临界区,确保互斥性;0或者多个条件变量,根据条件的个数决定,等待/通知信号量,并发访问共享数据 


lock acquire & release 可以写函数也可以是语言级的

condition variable 条件变量

wait() 释放锁,睡眠

signal / broadcast 唤醒等待者

类似信号量 要维持每一个条件队列


num waiting与信号量有差异,是等的队列的数目;signal不一定会使其减一


调用管程解决消费者生产者问题 
count记录了当前BUFFER的数据个数 

先在前后加锁,因为要保证只有一个线程在临界区 lock在等待/睡眠的时候通过notfull.wait(&lock)释放锁。唤醒后获得锁。



未完。。。。。。。。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值