◆◆◆
并发软件经常包含一些对象,其方法会被多个客户端线程调用。为了保护共享对象中的内部状态,有必要将客户端对它们的调用进行同步和调度。然而,为了简化编程,我们不希望客户端在编程的时候需要区分访问的组件是共享的还是非共享的。
每个会被多个客户端线程访问的对象应该确保其方法的序列化是透明的,不需要客户端做显式地干预。为了确保其客户端的服务质量,如果共享的对象中的某个方法在执行的过程中必须阻塞,它应该自动地放弃其控制线程,保证组件处于稳定状态,以便其他客户端线程可以安全地访问。
因此:
执行共享对象(的方法)应该是在其客户端线程中进行,并让它能够自己协调这个串行化而又交错的执行序列。必须通过同步的方法对共享对象进行访问,确保同一时刻只能执行一个方法。
每个Monitor Object包含一个监听者锁,用于访问对象状态时串行化。在一个同步的方法中,首先获得监听者锁,确保没有其他串行化方法可以执行。获得这个锁之后,检查共享对象的当前状态是否允许运行串行化方法。如果允许,则执行它,否则在某个条件上挂起对同步方法的执行。如果该方法的执行挂起在某个监听者条件上,监听者条件应该挂起调用者的线程,直到收到通知重新唤醒调用者线程。在线程挂起时,监听者条件应该释放监听者锁,并且在继续该线程的时候重新获取监听者锁。
挂起同步方法允许其他线程通过其他同步方法访问共享对象。任何同步方法在其执行结束时都可能会对监听者条件的有效性产生影响。这时应当通知相应的监听者条件,以便挂起的方法可以继续执行。在结束一个同步方法之前要释放监听者锁,以便其他线程调用的其他同步方法可以执行。
◆◆◆
将共享对象的类型设计为MONITOR OBJECT——通过在协作的线程中共享对象,并将方法调用和状态同步结合起来——简化了并发控制。MONITOR OBJECT对于实现方法执行序列之间的协作也有帮助,确保共享对象对客户端是可用的,并在序列化条件约束下最大化共享对象的可用性,确保其状态的变化是完整的而且不会带来竞争状态。然而,这个模式的缺陷是它把领域功能和同步功能紧密的耦合在一起。编写或者使用Monitor Object经常会带来死锁的问题。例如,如果一个Monitor Object回调了另一个对象,而这个对象使用了其他的Monitor Object,就很容易出现死锁。
Monitor Object可以使用THREAD-SAFE INTERFACE(384)来将同步行为和其他功能解耦合。这样两者就可以独立地变化了。GUARDED SUSPENSION(380)可以用于协调对象中运行的线程。方法的执行是由监听者条件和监听者锁来调度的,它们决定它们在什么情形下应当挂起,什么情况下应当继续执行。