标准答案
- 非原子复合操作可能被交错执行,导致丢失更新;要用锁、原子指令或数据库条件更新保护。
- 没有可见性保证时,一个线程可能读到旧值;要用锁、volatile/原子变量或消息传递建立同步关系。
- 编译器、CPU 和运行时可能重排无依赖操作;同步原语或明确的发布—订阅边界提供必要的顺序。
- 能不用共享可变状态时,优先使用不可变数据和消息传递降低内存模型复杂度。
题目解析
原子性、可见性和有序性分别回答“操作会不会被拆开交错”“别的执行单元何时能看到结果”“观察到的顺序是否满足约束”。一个变量的单次读写可能是原子的,但由读、改、写组成的计数器仍然会丢失更新。
同步原语提供的保证依赖语言内存模型,不能把 Java 的 volatile、Go 的 channel 或某个数据库隔离级别直接推广到所有运行时。回答时应说明同步边界和共享对象,而不是只报关键字。
如果能通过不可变快照、消息所有权或数据库原子条件避免共享可变状态,通常比在每个读写点补锁更容易验证;仍需说明消息重复、顺序和故障恢复。
常见误区
- 误区:把 volatile 当作复合操作原子性。改正:volatile 类机制通常解决可见性或部分顺序问题,计数器等复合更新仍需要原子操作或锁。
- 误区:认为单次读取和写入能自动保护计数器。改正:读取、计算和写回之间可以被交错,必须使用 CAS、锁或数据库条件更新。
- 误区:只给写入加锁,读取不使用同一同步边界。改正:读写必须遵守同一发布和同步协议,否则读取仍可能看到旧状态。