操作系统(十)- 信号量和管程

目录

1. 概述 

1.1 上次课内容的复习

1.2 结构图

2 信号量(实现同步和互斥)

2.1 概述 

2.2 机制的发现

3 信号量的使用

3.1 信号量是什么

4 信号量的具体实现

4.1 概述 

4.2 使用的例子,互斥

4.3 用信号量实现同步

4.4 更复杂的情况,二次信号量实现不了,例子如下(生消案例)

4.4.1 解决:每个约束用一个单独的信号量 

4.5 消费者案例的实现

4.6 p和v底层是怎末实现的

4.7 需要注意的问题

5 管程(抽象程度更高于信号量)

5.1 概述 

5.1.1 示意图

5.2 条件变量的实现

5.3 用管程解决消费者案例

5.4 signal操作的说明

5.5 总结

6 两个问题

6.1 读-写问题

6.1.1 读者优先,如果有读者在读,写者要先等待 

6.1.2 读者优先的实现

6.1.3 读者优先:建立管程大概的表现形式

6.1.4 根据上述的伪代码 实现代码

6.1.5 写者优先

 

6.2 哲学家就餐

6.2.1 最简单的想法(死锁:都拿自己左边的,结果就都饿死了)

6.2.2 改进,增加了对右边叉子的判断(还是不行,五个铁憨憨,一起拿,一起放,还是饿死了)

6.2.3 修改等待时间为随机时间,让他们不会同时放叉子,可行但不够完美(治标不治本)

6.2.4 每次拿叉子,就不允许其它人吃(可行,但只能一个人)

6.2.5 问题 

6.2.6 解决思路1

6.2.7 解决思路2--计算机版

6.2.8 解决思路3--程度

6.2.9 哲学家函数表示


 

1. 概述 

  1.  背景
  2. 信号量
  3. 信号量使用
  4. 信号量实现
  5. 管程
  6. 经典同步问题

1.1 上次课内容的复习

  • 并发问题:竞争条件(竞态条件)
    • 多程序并发存在大的问题
  • 同步
    • 多线程共享公共数据的协调执行
    • 包括互斥与条件同步
    • 互斥:在同一时间只有-个线程可以执行临界区
  • 确保同步正确很难?
    • 需要高层次的编程抽象(如:锁)
    • 从底层硬件支持编译

1.2 结构图

2 信号量(实现同步和互斥)

2.1 概述 

信号量: 

  •  抽象数据类型
    • 一个整形(sem), 两个原子操作
    • P(): sem减1,如果sem<0, 等待,否则继续
    • V(): sem加1, 如果sem<=0,唤醒一个等待的P

2.2 机制的发现

 

3 信号量的使用

3.1 信号量是什么

  •  信号量是整数
  • 信号量是被保护的变量
    • 初始化完成后,唯一改变一个信号量的值的办法是通过P()和V()
    • 操作必须是原子
  • P()能够阻塞,V()不会阻塞
  • 我们假定信号量是“公平的”,即在挑选唤醒哪一个线程时,是按照FIFO进行的,确保公平性。
    • 没有线程被阻塞在P ()仍然堵塞如果V ()被无限频繁调用(在同一个信号量)
    • 在实践中,FIF0经常被使用

 

4 信号量的具体实现

4.1 概述 

  •  可以通过两种类型信号量实现
    • 二进制信号量:可以是0或1
    • 一般/计数信号量:可取任何非负值
    • 两者相互表现(给定一个可以实现另-一个)
  • 信号量可以用在2个方面
    • 互斥
    • 条件同步(调度约束一--个线程等待另一个线程的事情发生)

4.2 使用的例子,互斥

4.3 用信号量实现同步

4.4 更复杂的情况,二次信号量实现不了,例子如下(生消案例)

  • 一个正确的方法,需要满足的要求: 
    • 在任何一个时间只能有一个线程操作缓冲区(互斥)
    • 当缓冲区为空,消费者必须等待生产者(调度/同步约束)
    • 当缓存区满,生产者必须等待消费者(调度/同步约束)

4.4.1 解决:每个约束用一个单独的信号量 

  •  每个约束用一个单独的信号量
    • 二进制信号量互斥
    • 一般信号量fullBuffers
    • 一般信号量emptyBuffers

4.5 消费者案例的实现

 

4.6 p和v底层是怎末实现的

4.7 需要注意的问题

  •  信号量的双用途
    • 互斥和条件同步
    • 但等待条件是独立的互斥
  • 读/开发代码比较困难
    • 程序员必须非常精通信号量
  • 容易出错
    • 使用的信号量已经被另一个线程占用
    • 忘记释放信号量
  • 不能够处理死锁问题

 

5 管程(抽象程度更高于信号量)

5.1 概述 

  • 提出时,是应用于语言的。
  • 目的:分离互斥和条件同步的关注
  • 什么是管程
    • 一个锁:指定临界区
    • 0或者多个条件变量:等待/通知信号量用于管理并发访问共享数据
  • 一般方法
    • 收集在对象/模块中的相关共享数据
    • 定义方法来访问共享数据
       

5.1.1 示意图

  •  Lock
    • Lock::Acquire() ——等待直到锁可用,然后抢占锁
    • Lock::Release() ——释放锁,唤醒等待者如果有
  • Condition Variable 
    • 允许等待状态进入临界区
      • 允许处于等待(睡眠)的线程进入临界区
      • 某个时刻原子释放锁进入睡眠
    • Wait() operation
      • 释放锁,睡眠,重新获得锁返回后
    • Signal() operation (or broadcast() operation)
      • 唤醒等待者(或者所有等待者),如果有

 

5.2 条件变量的实现

5.3 用管程解决消费者案例

5.4 signal操作的说明

5.5 总结

 

 

 

6 两个问题

6.1 读-写问题

6.1.1 读者优先,如果有读者在读,写者要先等待 

6.1.2 读者优先的实现

6.1.3 读者优先:建立管程大概的表现形式

6.1.4 根据上述的伪代码 实现代码

6.1.5 写者优先

 

6.2 哲学家就餐

6.2.1 最简单的想法(死锁:都拿自己左边的,结果就都饿死了)

6.2.2 改进,增加了对右边叉子的判断(还是不行,五个铁憨憨,一起拿,一起放,还是饿死了)

6.2.3 修改等待时间为随机时间,让他们不会同时放叉子,可行但不够完美(治标不治本)

6.2.4 每次拿叉子,就不允许其它人吃(可行,但只能一个人)

6.2.5 问题 

6.2.6 解决思路1

6.2.7 解决思路2--计算机版

6.2.8 解决思路3--程度

6.2.9 哲学家函数表示

函数take_forks

test_ take_ left_ right_ forks函数

put_forks

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值