通信建立的偏序
Lamport 的分布式系统定义把同一进程内的顺序、消息发送先于对应接收,以及这些关系的传递闭包结合起来。若两件事互不先行,就称为并发,而不是强行为它们指定一个已知的因果方向。
逻辑时钟可以为这种顺序分配数字:若甲先行于乙,甲的时钟值应更小。反过来,时钟值更小却不能单独证明甲先行于乙,因为数字也可能给本来无序的事件排出了次序。
参考:[1]
共享内存中的同步链
语言内存模型把相似思想用于内存操作。Java 规定,同一监视器上的解锁先行于后续加锁;线程启动、终止检测和 volatile 读写也有相应同步规则。
因此,可以通过同步把某线程写入的数据交给另一个线程使用。正确推理需要指出具体的同步链,不能用“这个线程大概晚执行了一点”代替内存模型规定的关系。
参考:[2]
原子性与顺序仍须区分
C++ 工作草案由先序、同步关系和传递性定义先行发生;release 写与读到该值的 acquire 读可以建立同步。宽松原子操作则不能因为“是原子的”就被当成同样的发布屏障。
各语言对数据竞争的后果不同。C++ 对满足其定义的非原子冲突访问规定未定义行为,Java 的规则不能直接套用过去;分析时必须说明采用哪种语言与哪些操作。
参考:[3]