ArtOfMP--笔记

课程主页
http://cs.brown.edu/courses/cs176/

理解计算机系统是异步的:

  • 任何活动都可能由于中断、抢占、缓存缺失、故障等事件而停止或延迟;
  • 这些延迟都是不可预测的,规模可大可小:缓存缺失导致延迟的指令数少于10个,页面缺失导致延迟的指令多大几百万个,操作系统抢占导致延迟的指令数多达上千万个;

存在一些共享对象:容易描述,但不能被任何并发算法实现;

  • 这些共享对象有哪些?
  • 不要花费力气去实现这种类型的共享对象;

并发共享内存模型

  • 描述
  • 涉及哪些计算问题?(程序的正确性+)
  • 哪些是并发共享内存模型可以实现的?哪些是并发共享内存模型不能实现的?

顺序程序的正确性

  • 跟安全性有关;

顺序程序的安全性

  • 描述
    坏的事情永远都不会发生
  • 示例
    即使断电了,交通灯永不会在所有方向都显示绿色

并发程序的正确性

  • 比顺序执行程序更复杂,需要不同的工具,及非正式的推理;
  • 跟安全性有关,但更复杂
  • 跟活性有关,这是顺序程序没有的

并发程序的安全性

  • 描述
    无论多个并发线程怎么进行交叉执行,都必须保证坏的事情永远不会发生

并发程序的活性

  • 描述
    某种好的事情总会发生
  • 示例
    交通灯总会变绿的

顺序程序的性能分析

  • 描述
    基于一系列完善且易于理解的抽象;
    不需要了解顺序程序执行时底层到底发生了什么,
    比如页面从硬盘swap到内存,
    在处理器缓存层间移进和移出比页面更小的内存单元;
    在顺序程序里,通过简单的编程抽象,这种复杂的内存层级是不可见的;

并发程序的性能分析

  • 描述
    不同于顺序程序的性能分析,并发编程需要底层复杂的内存层级结构,
    了解顺序程序执行时底层到底发生了什么,
    比如页面从硬盘swap到内存,
    在处理器缓存层间移进和移出比页面更小的内存单元;

共享对象示例

  • 自旋锁
  • 链表

自旋锁

  • 描述
    说明并发程序之间的竞争;
  • 对程序性能有什么影响?

链表

  • 描述
    说明锁在数据结构设计中的角色;
  • 对程序性能有什么影响?

并发相关问题

  • 互斥问题
  • 死锁问题
  • 有界公平问题
  • 阻塞同步和非阻塞同步问题

并发调度问题示例
Alice和Bob是邻居,共用一个院子。
Alice有只猫,Bob有只狗。
两只宠物都喜欢在院子里跑,但是不能和平相处。
问题:怎么保证两只宠物永远不会同时出现在院子里?

平凡解:
不允许两只宠物进入院子;

方案一:
院子很大,Alice不能简单地看下窗户来判断Bob的宠物在不在院子里。
Alice可以直接走到Bob的房子前,然后敲门来确认,缺点是花费时间太久;

方案二:
Alice推开窗户,大声叫Bob,问其可以放猫出去吗,问题是Bob可能听不到,
因为Bob可能在看电视,可能去看女朋友了,可能出门给宠物买食品了等。

方案三:
通过手机来调度,问题是如果Bob在洗澡,或者在隧道里开车,
或者在给手机充电,则Bob就接收不到Alice的电话了。

方案四:
Alice在Bob的窗台上放置多个空的啤酒罐,在每个啤酒罐周围系上一个绳子,
拉着绳子回到自己房子。
Bob也这样做。
当Alice想给Bob发信号时,她就使劲摇绳子直至撞倒一个啤酒罐。
当Bob注意到一个啤酒罐被撞倒时,他就重置这个啤酒罐。
问题是Alice可以放置的啤酒罐的数量是有限的,很快就会撞倒所有的啤酒罐。
当然,Bob可以一注意到有个啤酒罐被撞倒,就重置这个啤酒罐。
但是,如果Bob去度假了,则总会出现所有的啤酒罐都被撞到了的情况。

方案五:
Alice和Bog各自竖一个容易被看到的旗杆。

当Alice想放她的猫到院子时,Alice就会

  1. 升起她的旗子;
  2. 当Bob的旗子没升起时,她就放她的猫到院子里;
  3. 当她的猫回来时,她就降下她的旗子;

当Bob想放他的狗到院子时,Bob就会

  1. 升起他的旗子;
  2. 只要Alice的旗子还升着,则
    a)Bob就降下他的旗子;
    b)Bob会一直等待直到Alice降下她的旗子;
    c)Bob升起他的旗子;
  3. 他的旗子被升起且Alice的旗子没升起,Bob就放他的狗到院子里
  4. 当他的狗回来时,他就降下他的旗子;

旗子定理

如果Alice和Bob每个人都:

  1. 升起各自的旗子,然后
  2. 看一下对方的旗子,

    (1)至少有一个人会看到对方的旗子已经升起,不会放其宠物到院子里;
    (2)两只宠物永远都不会同时出现在院子里(安全性-互斥性);
    (3)如果有一只宠物想进入院子,则其最终会进入的;
    (4)如果两只宠物都想进入院子,则最终至少有一只会进入;
    (5)不满足免饥饿性,即如果每当有冲突时,Bob总是顺从Alice,则
    有可能Alice的猫一直在使用院子,而Bob的狗就会越来越不耐烦;
    (6)不满足无等待性:如果Alice升起她的旗子后,突发阑尾炎。接着,她和猫一起被带到了医院。在接受了成功的手术之后,又留院观察了一个礼拜。虽然Bob得知Alice身体好后长舒了一口气,但是他的狗不能使用院子一个礼拜直到Alice回来。因为协议描述到Bob和他的狗必须等待Alice降下她的旗子。如果Alice被延后了,则Bob无条件被延后;

证明:

假定表示Alice升起她的旗子,
表示Alice看Bob的旗子有没有升起,
假定表示Bob升起他的旗子,
表示Bob看Alice的旗子有没有升起,

根据旗子定理的假设可知,A_1->A_2,B_1->B_2;

从而有以下6种可能的并发执行方式:

  1. A_1->A_2->B_1->B_2

  2. A_1->B_1->A_2->B_2

  3. A_1->B_1->B_2->A_2

其余三种类似。

可用反证法证明(2)

反证:
假定Alice和Bob的宠物都出现在院子里,则:
Alice的猫出现在院子里,必有A_2->B_1,即A_1->A_2->B_1->B_2;
Bob的狗出现在院子里,必有B_2->A_1,即B_1->B_2->A_1->A_2,
从而有B_1->A_2,矛盾;

互斥性

无死锁

无饥饿

无等待
Bob和Ailce协议的有点是满足了互斥性和无死锁,缺点是不满足无等待,不满足无饿死;

方案二:大喊方案--瞬时通信
Alice推开窗户,大声叫Bob,问其可以放猫出去吗,问题是Bob可能听不到,
因为Bob可能在看电视,可能去看女朋友了,可能出门给宠物买食品了等。

方案三:打电话方案--瞬时通信
通过手机来调度,问题是如果Bob在洗澡,或者在隧道里开车,
或者在给手机充电,则Bob就接收不到Alice的电话了。

方案四:can-string协议--中断通信
Alice在Bob的窗台上放置多个空的啤酒罐,在每个啤酒罐周围系上一个绳子,
拉着绳子回到自己房子。
Bob也这样做。
当Alice想给Bob发信号时,她就使劲摇绳子直至撞倒一个啤酒罐。
当Bob注意到一个啤酒罐被撞倒时,他就重置这个啤酒罐。
问题是Alice可以放置的啤酒罐的数量是有限的,很快就会撞倒所有的啤酒罐。
当然,Bob可以一注意到有个啤酒罐被撞倒,就重置这个啤酒罐。
但是,如果Bob去度假了,则总会出现所有的啤酒罐都被撞到了的情况。

操作系统里的中断机制

  • 描述
    在现代操作系统里,一个线程得到另一个线程关注的常用方式就是向它发送一个中断:
    线程A在一个位置设置了一位变量,线程B周期性地检测这个变量。不久以后,线程B发现这个变量位被设置了,并作出响应。线程B在响应后就把这个位变量重置了,线程A不能重置这个位变量。
  • 中断不能解决互斥问题,但还是有用的,比如中断通信是Java里的wait()和notify()方法的基础

方案二和方案三代表的是实时通信,要求双方都同时参与。

瞬时通信要求双方都同时参与

持久通信允许发送者和接收者在不同的时间参与通信,比如寄信、发邮件、在石头上留笔记等;

互斥性需要的是持久通信。

方案五:
Alice和Bog各自竖一个容易被看到的旗杆。

当Alice想放她的猫到院子时,Alice就会

  1. 升起她的旗子;
  2. 当Bob的旗子没升起时,她就放她的猫到院子里;
  3. 当她的猫回来时,她就降下她的旗子;

当Bob想放他的狗到院子时,Bob就会

  1. 升起他的旗子;
  2. 只要Alice的旗子还升着,则
    a)Bob就降下他的旗子;
    b)Bob会一直等待直到Alice降下她的旗子;
    c)Bob升起他的旗子;
  3. 他的旗子被升起且Alice的旗子没升起,Bob就放他的狗到院子里
  4. 当他的狗回来时,他就降下他的旗子;

方案5满足互斥性和无死锁,表明两个线程之间的互斥问题可通过只使用两个1位的变量来解决:每个变量被一个线程写,被另一个线程读。

你可能感兴趣的:(ArtOfMP--笔记)