操作系统笔记——第10章 信号量、管程

背景

操作系统存在并发问题:竞态条件,即多程序并发存在大的问题

操作系统同步指多线程共享公共资源的协调执行,包括互斥和条件同步。互斥指同一时间只有一个线程可以在临界区执行。

实际条件中,确保同步正确很难。需要高层次的编程抽象(如:锁)和底层硬件支持编译。

信号量和管程是比lock更高级的解决方法。

信号量

信号量(sem)是抽象数据类型:

  • 一个整形(sem),两个原子操作(P【减】,V【增】,荷兰语)
  • P():sem减1,如果sem<0,等待,否则继续
  • V():sem加1,如果sem<=0,唤醒一个等待的IP

信号量的使用

  • 信号量是整数,初始值一般设为大于0 的数,在P操作的时候不会阻塞
  • 信号量是被保护的变量
    • 初始化完成后,唯一改变一个信号量的值的方法是通过P( )/V( )
    • 操作必须是原子
  • P( )能够使进程阻塞/挂起,V( )能唤醒进程
  • 假定信号量是“公平的”
    • 没有线程被阻塞在P( )仍然阻塞如果V( )被无限频繁调用(在同一个信号量)
    • 在实践中,FIFO经常被使用
  • 信号量有两种类型
    • 二进制信号量:0/1,与lock达到相同功能
    • 一般/计数信号量:可取任何非负值
    • 两者相互表现(给定一个可以实现另一个)
  • 信号量可以用在两个方面
    • 互斥
    • 条件同步(调度约束 - 一个线程等待另一个线程的事情发生)
  • 用信号量实现互斥

信号量的实现

管程(monitor)

目的: 分离互斥和条件同步的关注

管程:

  • 一个锁:指定临界区
  • 0或多个条件变量:等待/通知信号量用于管理并发访问共享数据

一般方法:

  • 收集在对象/模块中的相关共享数据
  • 定义方法来访问共享数据

条件变量Condition Variable:

扫描二维码关注公众号,回复: 12974613 查看本文章
  • 允许等待状态进入临界区
    • 允许处于等待(睡眠)的线程进入临界区
    • 某时刻原子释放锁进入睡眠
  • wait() operation
    • 释放锁,睡眠、重新获得锁后返回
  • signal() operation(or broadcast() operation)
    • 唤醒等待者(或所有等待者),如果有

实现:

  • 线程以互斥的方式(lock)进入管程(entry queue)
  • 进入管程的线程开始执行管程内部维护的函数
  • 执行函数过程中,需要对共享资源进行等待的时候,当前线程挂起在相应的条件变量上,并释放lock(条件变量下是挂起的队列,当满足条件变量的时候,唤醒线程。对条件变量有两个操作:wait x/signal x)

如果在管程中线程A睡眠,会唤醒另一个线程B进入管程,那么在A的lock release前,线程的执行顺序一般是先执行A到lock release然后执行B(Hansen-style)。

经典同步问题

  • 读者和写者问题
  • 哲学家吃饭问题

信号量和管程的总结

在这里插入图片描述
同步结构:

  • 锁:互斥
  • 条件变量:有条件的同步
  • 其他原语:信号量

猜你喜欢

转载自blog.csdn.net/MaoziYa/article/details/106649014
今日推荐