从冯诺依曼到面向对象,为什么说宏观世界没有真正意义上的并行

2 阅读8分钟

背景

冯诺依曼架构的核心是内存、状态、指令、状态变迁。内存是空间,数据存储在地址里,程序是对空间的读写操作。程序本质上描述的是:某个时刻,内存里有什么东西。

这套模型非常强大,其本质上是一种空间隐喻

面向对象继承了这套世界观,并把它封装得更精致:类、对象、继承、组合。对象是有名字的空间,方法是对这个空间的操作。OOP 几乎完全是空间隐喻的体现——包含、嵌套、层级、结构——却几乎没有时间隐喻——事件、演化、裁决、因果。

然而随着软件工程的不断发展,其最大的工程复杂度几乎全部来自时间:并发编程,分布式,一致性,事务,消息,超时,同步。

在面向对象的世界观中:

世界=当前状态\text{世界} = \text{当前状态}

世界的变化实际上就是:

状态1状态2状态3\text{状态}_1 \rightarrow \text{状态}_2 \rightarrow \text{状态}_3

因果被私有化、分散化。每个对象都持有自己的状态(空间的切片),用自己的方法修改自己的状态,或者用回调方法去修改其他对象的状态(空间内容的变更)。

历史因此被切碎成无数碎片,散落在无数对象的私有空间中,没有统一的因果叙事在守护身份连续性。

空间模型追求静态的清晰:边界明确、层级清楚、组合直观。时间模型追求动态的清晰:因果可追溯、历史可叙述、冲突可裁决。

当一个问题是时间性的,却被迫用空间结构表达时,时间就会被切碎、隐藏、私有化。

本质是用空间建模的方式耦合时间维度。


双世界理论

双世界理论主张:对于持续存在的系统,必须在建模上明确区分世界事实如何形成,以及世界如何被感知和呈现

前提:任何在时间中持续存在、并且必须不断与外部交换信息的复杂系统,都同时面临两个要求:

  1. 它必须保持自身的历史连续性。
  2. 它必须持续吸收外部变化。

一个系统如果完全忽略外部变化,它会逐渐脱离环境,失去适应能力。但如果每一次变化都完全覆盖过去,那么系统也无法形成历史、上下文和身份。

因此,一个持续存在的世界,必须不断将新的变化纳入已有历史,使未来建立在过去的基础之上。

于是,系统会逐渐分化出两套相互协作的机制:

  • 因果层:负责接收事件、解释事件、裁决关系变化、维护可解释的事实历史。它的核心资产是事实历史和裁决规则,待裁决事件作为输入进入裁决过程。它对应的是时间维度——事件的不可逆、因果的单向性。
  • 感知层:负责感知环境、处理变化和形成体验。接触外部世界,把外部变化翻译成系统可以消费的信息。它对应的是空间维度——多元感官的同时展开、多种呈现方式的并行存在。

两者通过持续反馈形成闭环。

外部世界 → 感知层检测 → 上报事件 → 因果层裁决
                                ↓
外部世界 ← 感知层呈现 ← 消费事实 ← 下发事实

因果层

有一个古老的哲学问题:世界是由什么组成的?一类回答是实体,对应的是面向对象,另一类回答是关系。因果层的核心设计根植于后者,即过程哲学。

状态只回答:世界现在是什么样?

但持续存在的系统还必须回答另一个问题:

世界为什么会变成现在这样?是什么导致了状态的变化?

因果层的本质是维护世界的历史连续性与因果可解释性。

例如,玩家发起一个攻击事件:

发起攻击
  ↓
造成伤害
  ↓
血量归零
  ↓
角色死亡

状态只是这些历史事实在当前时刻的投影,是一种派生产物。

Player.hp = 0
Player.dead = true

如果导致状态发生变化的事件不存在,那状态本身就毫无意义。

外部世界往往趋向于一种无序的熵增,无数变化同时发生,不可解释,不可信任。

任何需要持续存在的系统,就必须拥有一种机制,将外部事件解释为稳定、可追溯的历史。这种机制在因果层中被称为裁决

  • 合法性判定:这个请求是否满足生效条件?例如施法者是否被沉默、账户余额是否充足、账户是否存在风险。
  • 语义转换:这个事件意味着什么?例如一次命中是普通伤害、暴击还是被闪避;一次交易是成立、失败还是需要回滚。
  • 冲突裁决:当多个事件相互矛盾或同时发生时,系统必须给出唯一事实版本。例如两个人同时修改同一行数据、同时拾取同一个物品、同时越过终点。
  • 操作系统触发 syscall、interrupt,内核就需要解释谁取得了 CPU 的时间片,谁占据了事件总线。
  • 两个人同时越过终点,观众本身无法分辨,但是裁判一定会给出谁先谁后的裁决。
  • 两笔区块链交易同时花费同一笔资产,两笔交易都被广播、被矿工看到,但共识机制必须解释:哪笔交易进入历史,哪笔交易失效,哪个区块成为主链。
  • FPS 游戏中,两个玩家同时开火,游戏服务器必须解释:谁先命中,谁先死亡。

这就是为什么可解释性如此重要。因为外部世界产生的变化天然是无序的、并发的,甚至可能相互冲突。

可解释的本质就是因果可追溯。一个事实如果无法追溯其来源,那事实所对应的状态就无法解释其形成过程。


最终因果一致性

任何需要形成稳定世界的过程,都不能允许事实长期悬而不决。

因果层一旦做出裁决,系统就在有限时间内收敛到该裁决所确定的事实版本。这就是最终因果一致性。它强调:

  • 呈现可以滞后
  • 感知可以插值
  • 局部可以暂时不一致

但在有限空间,有限时间内,所有参与者最终必须面对同一个事实版本,形成完整可追溯的因果链。

宏观世界永远没有真正意义上的并行。

你可以把它理解成:

宏观系统可以存在大量并行的变化,但如果这些变化需要共同构成一个稳定世界,它们最终必须被纳入同一个可解释的历史。

这很关键。我们感知中的"同时"——两个人同时挥剑、两颗子弹同时命中、两个线程同时运行——本质上都只是局部观察下暂时无法分辨先后

但只要世界需要给出结果、状态需要收敛、事实需要成立,系统最终就必须形成一个可解释的因果顺序。否则世界无法稳定。

这其实就是裁决为什么不可避免。

比如游戏里的"同时攻击":两个角色同时砍死对方。看起来:

A hit B
B hit A

同时发生。但因果层一定要回答:谁先死亡?死亡后技能还能不能触发?吸血效果是否成立?死亡爆炸是否发生?仇恨归属怎么算?

于是系统必须裁决。哪怕玩家感觉是同时、动画也是同时、特效也是同时——因果层仍然必须裁决

版本控制:多个开发者同时修改同一行代码,Git 会尝试自动合并;如果冲突无法自动解决,就必须有人工裁决。

数据库事务:多个用户同时修改余额。物理世界里 CPU 并行、网络并行、请求并行,但数据库必须裁决先后顺序。否则钱会凭空消失、状态腐化、世界失真。

法律系统:两个人互相指控,但法院最后一定形成一条可叙述的因果链。因为社会秩序和媒体大众都需要一个"事实版本"。

宏观世界这个词非常重要。因为微观层面,可能确实存在:

  • 量子叠加
  • 概率态
  • 真并发
  • 非决定性

但一旦进入宏观层面,世界就必须收敛成可叙述现实

为什么?因为宏观系统需要稳定因果

否则:

  • 无法观察
  • 无法推理
  • 无法协作
  • 无法预测
  • 无法治理

换句话说:文明本身就是建立在最终因果可排序之上的。

原文链接