并发, 时间是一个本质问题.

时间的性质

只要尝试模拟你所感知的世界, 它就必须是并发的.

是与否的距离, 大概有几纳秒吧.

你看到的顺序不是真正的顺序.

你只是不在这个维度的宇宙. 变化之后的世界数量难以想象.

时间是一种设施, 发明它就是为了不让所有的事情都立即发生.

共享造就了分叉. 读是这种设施的分叉点.

谁也不知道谁读了之后做了什么. 直到它们在不同的时刻回归设施.

真相转瞬即白, 转瞬即灭. 微妙的结果也许马上就被从那个世界抹去.

并发程序的正确性为

那里只能容忍一个结果.

内在的非确定性是关键.

一集可能的值都会是潜在的结果. 一只猫在安静地舔舐牛奶.

组合可以得到所有的可能值. 只是穷遍这夜空中所有的星星数量也未可及.

控制并发的机制

串行的世界没有分叉, 死亡既是重生.

是是非非, 是非是非, 触手可及.

Ex3.39

a: (s (lambda () (* x x))) b: (set! x a) c: (s (lambda () (set ! x (+ x 1)))

可能性: (a: (b: c), (c, b)) (c: (a: b))

101, 100, 121

Ex3.40

2(2(2(21)) + 2(2(2(2(1))))) = 2*(8+64)=144种可能的执行顺序 结果的可能性有: 翻2倍, 翻3倍, 翻4倍, 翻5倍, 翻6倍, 五种情况.

序列化之后, 有两种执行顺序的可能性, 但结果都是翻5倍.

Ex3.41

充值和退款两种操作都被串行执行, 即便非串行访问银行账户也无法得知中间状态. 把充值, 退款, 和查账 3种操作以任意组合调用, 产生的结果都是合法的可能值.

潜在的问题是: ‘balance 一般是用来查账的. 如果需要先查账在做某些操作(即check-and-set 操作), 这个操作也需要被串行化. 仅就Ben提到的访问需求, 大可不必串行化.

Ex3.42

没差

话说, 如果Ben做了两个Serializer的话, 应该会有问题吧? 比如 withdraw, deposit 交替执行的话可能会因为没有串行保障而诡异起来?