You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

结合Volatile与Synchronized能否实现可见性与原子性?两种方案对比

两种计数器方案的效果对比与分析

直接给结论:这两种方案功能完全等价,都能实现线程安全的计数器,第二种方案没有问题,甚至在读取性能上更优。

方案一的原理

方案一中,getCount和increment都通过synchronized(this)锁住当前对象:

  • synchronized既保证了同一时间只有一个线程能进入同步块(互斥性),还会在进入同步块时刷新主内存数据到线程缓存,退出同步块时把线程缓存的修改同步回主内存(可见性)。
  • 对于counter++这种拆分成「读值-加1-写回」的非原子操作,同步块能确保这三步不会被其他线程打断,保证了操作的原子性。

方案二的原理

方案二用volatile修饰counter,同时给increment方法加synchronized:

  • volatile的核心作用是保证变量的可见性:每次读取counter时都会直接从主内存获取最新值,不会使用线程本地缓存;每次修改后也会立刻同步回主内存。但volatile不保证原子性,单独用它修饰counter的话,counter++会存在线程安全问题。
  • 而increment方法的synchronized修饰符,刚好弥补了volatile的原子性缺陷——同一时间只有一个线程能执行这个方法,确保「读值-加1-写回」的完整流程不会被打断。同时synchronized退出时的内存同步机制,搭配volatile的可见性,能保证其他线程调用getCount时总能拿到最新的counter值。

为什么第二种方案没问题?

很多人习惯用第一种方案,可能是觉得「所有操作都加锁更稳妥」,但实际上方案二的设计更高效合理:

  • 读取操作getCount只需要保证可见性,不需要原子性,volatile完全能满足需求,省去了加锁带来的上下文切换开销。
  • 写操作increment需要原子性,用synchronized保证即可,结合volatile的可见性,整个计数器的读写都是线程安全的。

所以两种方案都能正确实现线程安全的计数器,在读取场景更多的业务中,第二种方案的性能表现会更优。

内容的提问来源于stack exchange,提问作者itspr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:25:07