线程间同步,需要等待。等待对于同步的重要性是不言而喻的。
考虑一个工厂的流水线,假设工序1和工序2没有关联,那么找两个工人各干的就可以,这两个工人都可以不认识对方。
现在考虑的重点是工序1和工序2有关联。那么两个工序就需要某种形式的沟通和同步。
第一种情况:工序1进行到某个时间点时,需要工序2结束。
1)工序1暂停,在工序1上干活的工人可以暂时离开这个工序,去休息,或去别的地方帮忙。
2)工序2加紧赶工。
3)工序2完成。
4)经理通知工序1继续,指派一个工人去做工序1。
这种同步的特点是:
1)工序1停工等待(join())。
2)当工序1继续时(从join()调用返回),工序2在的事情已经完成。
3)工序2一定是之前发生的(happen-before)。
4)工序2的工作完整成果对工序1可见。
第二中情况:工序1和工序2需要独占一个公共资源,比如去原料仓库取货。
1)工序2的工人(他代表工序2)来到仓库取货,管理员让他进入拿货,清点,并作登记。
2)工序1的工人知道仓库一次只能去一个人,就坐在那里等待(或去其它地方帮忙),实际上等同于工序1暂停了。
3)工序2的工人取货回来。
4)工序1的工人才能去仓库取货。
这种同步的特点是:
1)工序1进入仓库(lock())这个过程很长,可能会长时间等待,甚至可能要排队。
2)工序2的仓库中出来(unlock()),工序1才能完成进入仓库事件(lock())。
3)工序2.拿料事件e发生在工序2.离开仓库事件之前,工序1.拿料事件f发生在工序1.进入仓库事件之后
4)工序2.拿料事件e就发生于工序1.拿料事件f之前(happen-before)
5)工序2在仓库中的所有活动结果对工序1可见。例如:工序1的人可以看到,工序2的人拿走一大半原料,因此影响到自己只能拿很少的原料了。
第三种情况:工序1和工序2需要某种“快速的“完成通知。
1)工序1的人不停的盯着一个指示灯
2)工序2的人把生产出的半成品放入堆放区
3)工序2的人点亮指示灯
4)工序1的突然注意到指示灯亮了
5)工序1的人去堆放区取出半成品
这种同步的特点是:
1)工序1的人要经常盯着指示灯
2)工序1的人可以不停工
3)工序2中,事件顺序为:半成品制作->推送到堆方区->打开指示灯
4)工序1中,事件顺序为:发现指示灯亮->从堆放区取东西->处理半成品
5)工序2【制作半成品事件】一定发生在工序1【处理半成品事件】之前(happen-before)
6)可以采取灵活的等待策略,例如:”紧盯“策略,眼睛一刻也不离。还可以采取隔一段时间去瞅瞅指示灯的策略。也可以先暂时离开工序1去扫扫地,回头再看。