把数据访问集中在受控边界内

多个线程或进程共享一个对象时,管程将受保护数据和操作这些数据的过程放在一起,入口保证同一时刻只有一个执行者进入有关受保护代码。调用者通过这些操作使用状态,而不是随意在外部修改内部字段。

Lampson和Redell介绍Mesa管程时,区分可从外部调用的入口过程与内部过程,并说明并非模块中每个过程都必须持锁。组织边界应跟共享状态相配合,不能因为代码属于同一模块,就让所有无关计算也长期占住锁。

参考:[1]

互斥与条件等待配合

持锁并不代表资源一定可用。若分配器暂时没有足够空间,调用者要在条件变量上等待并释放管程锁,让释放资源的其他执行者有机会进入;返回前再取得锁,并重新检查是否满足请求。

管程还需要维护状态不变式。修改内部结构期间可以暂时处于中间状态,但在退出受保护入口或开始等待前,应恢复其他执行者可以依赖的约束。自动加锁不能替程序员决定这些数据之间应保持什么关系。

参考:[1]

唤醒语义和死锁边界

Mesa论文对比Hoare的立即交接语义与Mesa的通知语义:后者让被通知者在稍后重新竞争进入,不保证通知时成立的条件仍保留给它。这个设计差别决定等待端怎样证明继续执行是安全的,不能只凭“管程”名称猜测唤醒规则。

管程也不自动消除死锁。两个管程相互调用,或等待的条件只能由被外层锁挡住的执行者建立,仍可能永久阻塞;嵌套边界、资源顺序及条件协议必须一起设计。管程提供结构化同步工具,不是所有并发问题的自动解答。

参考:[1]