标准答案
- 单个整数的 increment 应使用运行时提供的原子操作或数据库原子更新。
- 读取和更新多个相关字段时,单个原子变量不够,需要同一同步边界保护整个不变式。
- 高竞争计数可使用分片计数后汇总,但读取会有近似或合并成本。
题目解析
单个计数器的递增需要原子 read-modify-write,普通 value++ 通常包含读取、加法和写回三个步骤,并发时可能丢失更新。运行时原子操作或数据库原子更新可以保护这个单变量不变式。
如果需要同时更新多个计数、判断阈值或维护余额与记录,单个原子变量不够,必须使用同一锁、事务、CAS 循环或按 Key 串行化保护复合不变式。
高竞争计数可以使用分片计数后汇总,但读取可能是近似或需要合并。语言级原子通常只在进程内有效,跨进程要依赖共享存储或协调协议。
代码示例
伪代码示意:
TypeScript
class Counter {
private value = new AtomicInteger(0)
increment() { return this.value.addAndGet(1) }
get() { return this.value.get() }
}常见误区
- 误区:用普通 value++ 声称线程安全。改正:使用原子递增、锁或数据库条件更新,并说明作用域。
- 误区:把语言级原子变量当作跨进程共享。改正:跨进程使用数据库、共享内存或专门的协调存储。
- 误区:多个计数之间有不变式却分别原子更新。改正:把复合状态放进同一同步或事务边界。