六、并发:互斥与同步(三)

4.4管程

  • 动机
    • 同步机制与同步策略分离产生灵活性的优势,同时容易产生危险
    • 集中管理(封装)已策安全
  • 管程是一种封装同步机制与同步策略的程序设计语言结构
    • Ada 95、并发Pascal、Modula-3、Java、C#、Delphi、Python、Ruby、Mesa等
  • 1972年由英国计算机科学家C.A.R. Hoare和美籍丹麦计算机科学家P.B. Hansen发明

4.4.1使用信号的管程

  • 1974年Hoare提出的管程方案
  • 1975年Hansen在并发Pascal上实现
  • 主要特点
    • 本地变量只能由管程过程访问(封装)
    • 进程通过调用管程过程进入管程(调用)
    • 每次只能一个进程执行相关管程的过程(互斥)
  • 主要缺陷
    • 可能增加了两次多余的进程切换
    • 对进程调度有特殊要求(不允许插队)
  • 管程的结构和应用
    • 管程软件模块的组成
      • 若干过程
      • 一个初始化序列
      • 局部数据
      • 条件变量
        image
        image
  • 管程提供的互斥机制
    • 管程中的数据每次只能被一个进程访问
    • 可将共享数据结构放入管程以得到保护
    • 可用这些资源代表临界资源
  • 管程对同步的支持
    • 通过cwait(c)、csignal(c) 操作管程中的条件变量实现同步
  • 有限缓冲区生产者/消费者的管程解决方案A
    image
  • 使用信号的管程存在的问题
    • 两次额外的进程切换问题
      • 管程内只允许一个活动的进程
      • 在条件队列中至少有一个进程时,若有一个进程对条件变量进程csignal操作,本进程要立即脱离互斥区,即必须退出管程(或阻塞在管程上)以便让队列中被唤醒的进程能够立即进入管程运行
      • 如果产生csignal信号的进程在管程内的运行还未结束,则需要两次额外的进程切换(阻塞当前进程,运行结束后再恢复其他进程)
      • 进程调度程序必须保证在激活被唤醒的进程前没有其他进程进入管程,否则可能造成永久阻塞
    • 解决办法:采用使用通知和广播的管程

4.4.2使用通知和广播的管程

  • 1980年2月美国计算机科学家B. W. Lampson和D. D. Redell为Mesa语言开发的一种管程方案(也可用于Modula-3)
  • 主要特点
    • 用cnotify原语代替原来的csignal操作
      • 发通知的进程不需要立即退出管程;接到通知的进程也不需要立即被唤醒,只是转为就绪;等待合适的时候再进入管程运行
    • 用while循环代替if判断
      • 引入额外的条件变量检查
      • 避免额外的两次进程切换
    • 增加计时器,等待超时的进程将被转为就绪态
  • cnotify原语
    • 通知特定等待条件队列中的第一个等待进程,但当前执行cnotify原语的进程继续执行
    • 被通知的等待进程转为就绪,但必须重新检查条件
  • cboradcast原语
    • 通知特定等待条件队列中的所有等待进程,但当前执行cnotify原语的进程继续执行
  • 有限缓冲区生产者/消费者的管程解决方案B
    image

4.5消息传递

  • 进程交互的两个基本要求
    • 同步:互斥进程间需同步,同步指对进程执行时序约束,包括互斥和时序的先后顺序
    • 通信:合作进程间交换信息
  • 消息传递
    • 进程间通信的一种方法
    • 适用范围广,可用于多核、SMP和分布式系统
    • 原语send(发送)和receive(接收)
      • send(目的,消息)
      • receive(源,消息)
    • 实现的形式有多种
  • 信息传递自然地隐含了同步
    • 只有一个进程发送消息之后,接收者才能收到消息
  • 调用send原语的两种可能结果
    • 发送者进程被阻塞,直到这个进程被接收
    • 发送者进程不被阻塞
  • 调用receive原语的两种可能结果
    • 接收者进程接收消息时,消息已发出,接收者不阻塞
    • 接收者进程接收消息时,消息未发出,接收者被阻塞,直到发出者进程发出此消息
  • 消息传递实现的三种常用组合方式
    • “阻塞send,阻塞receive”方式,即“会合原则”,适用于进程间的紧密同步(如打电话)
    • “无阻塞send,阻塞receive”方式,最有用的组合(如收发短信)
    • “无阻塞send,无阻塞receive”方式,不要求任何一方等待。危险:信息可能丢失
  • “无阻塞send”是最自然的选择。但错误可能会导致进程间重复传递消息,消耗系统资源。且必须使用应答消息以证实收到消息
  • “阻塞receive”是常用的选择。但若消息丢失或发送者进程失效,会导致接收者进程被长期阻塞

4.5.2消息传递的寻址

  • send原语中指明接收者是必要的
  • receive原语有时也指明发送者
  • 直接寻址方案
    • 发送者在发送时给出了接收者进程的具体标识号,如进程ID
  • 间接寻址方案
    • 发送者将消息发送到共享的信箱中临时保管,接收者从信箱中获得这些消息
    • 耦合方式:“一对一”、“多对一”、“一对多”或“多对多”
    • 进程与信箱的关联:静态方式(端口)和动态方式(使用原语connect和disconnect)

4.5.3消息格式

  • 取决于运行环境
    • 单机系统
    • 分布式系统
  • 两类格式
    • 定长格式
    • 变长格式
  • 消息格式
    image

4.5.4排队原则

  • 先进先出(FIFO)原则
  • 优先级原则

4.5.5消息传递实现互斥

  • 使用“无阻塞send,阻塞receive”
  • 一组进程共享一个信箱box,信箱被初始化为一条无内容的空消息(代表进入临界区的钥匙)
  • 每个进程在进入临界区前,首先尝试接收消息,离开临界区时将接收到的消息放回信箱
  • 每次只有接收到消息的那个进程才可以进入临界区(互斥)
  • 消息函数其实是在进程间传递一个可使用临界区的令牌
    image
  • 消息函数实现生产者消费者问题
    image

4.6读者写者问题

  • 问题描述
    • 有一个多个进程共享的数据区,有只读取该数据区的进程和只修改数据区的进程
    • 必须满足以下条件
      • 任意多的读进程可以同时读这个数据区
      • 一次只有一个写进程可以对数据进行写
      • 如果一个写进程正在往数据区中写,禁止任何读进程读数据区

4.6.1读者优先信号量方案

image
image

4.6.2写者优先信号量方案

image
image

基于消息传递的写者优先方案

image

posted @ 2024-11-16 12:08  韦飞  阅读(46)  评论(0)    收藏  举报