练习 3.42

Ben 的程序并不安全,而且会阻止单一对象进行并发。

考虑原本未修改的 make-account 程序,如果执行以下的求值序列的话,那么所有表达式都会被放进串行化组 protected 当中,其中每个操作符都是一个 protected 的串行化实例:

((protected withdraw) 10)

((protected withdraw) 20)

((protected withdraw) 30)

((protected withdraw) 40)

现在,想想使用 Ben 的 make-account 执行上面的求值序列会发生什么事情:它会用同一个 protected-withdraw 串行化对象处理所有调用请求:

(protected-withdraw 10)

(protected-withdraw 20)

(protected-withdraw 30)

(protected-withdraw 40)

假设解释器正在处理 (protected-withdraw 10) ,这时其他三个表达式也开始并发地运行,那么除了 (protected-withdraw 10) 之外,其他三个表达式都会出错,因为运行中的串行化进程是不能被其他过程所干扰的。

环境图对比

如果对 (protected withdraw)protected-withdraw 在环境图上进行对比,就会发现很明显的区别。

以下是未修改的 make-account 执行指定的调用序列时产生的环境图:

              ...
               ^
               |
+---------------------------------------------------------------------------------------------------------------+
|                                                                                                               |
| protected                                                                                                     |
|                                                                                                               |
+---------------------------------------------------------------------------------------------------------------+
     |                          |                          |                            |
     | ((protected withdraw)    | ((protected withdraw)    | ((protected withdraw)      | ((protected withdraw)
     |  10)                     |  20)                     |  30)                       |  40)
     |                          |                          |                            |
     v                          v                          v                            v
+----------------+     +----------------+       +----------------+              +----------------+
|                |     |                |       |                |              |                |
| 串行化地运行着  |     | 串行化地运行着  |       | 串行化地运行着  |              | 串行化地运行着  |
| (withdraw 10)  |     | (withdraw 20)  |       | (withdraw 30)  |              | (withdraw 40)  |
|                |     |                |       |                |              |                |
+----------------+     +----------------+       +----------------+              +----------------+

以下是 Ben 修改的 make-account 执行指定的调用序列时产生的环境图:

                                   +-------------------------+
                                   |                         |
                                   | protected               |
                                   |                         |
                                   +-------------------------+
                                       ^
                                       |
                                       |
                           失败    +-------------------------+
(protected-withdraw 20)\<--------------+                     |                 (protected-withdraw 10)
(protected-withdraw 30)+-----------> protected-withdraw <------------------+
(protected-withdraw 40)/ 尝试调用  | protected-deposit       |             |
                                   |                         |             |
                                   +-------------------------+             |
                                                                   +----------------+
                                                                   |                |
                                                                   | 串行化地运行着 |
                                                                   | (withdraw 10)  |
                                                                   |                |
                                                                   +----------------+

讨论

blog comments powered by Disqus