标准答案

  1. 单个整数的 increment 应使用运行时提供的原子操作或数据库原子更新。
  2. 读取和更新多个相关字段时,单个原子变量不够,需要同一同步边界保护整个不变式。
  3. 高竞争计数可使用分片计数后汇总,但读取会有近似或合并成本。

题目解析

单个计数器的递增需要原子 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++ 声称线程安全。改正:使用原子递增、锁或数据库条件更新,并说明作用域。
  • 误区:把语言级原子变量当作跨进程共享。改正:跨进程使用数据库、共享内存或专门的协调存储。
  • 误区:多个计数之间有不变式却分别原子更新。改正:把复合状态放进同一同步或事务边界。

作者信息