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

Java并发场景下Volatile+Synchronized与全Synchronized实现选型咨询

两种实现方案对比结论

第一种volatile+仅flip方法加synchronized的方案存在竞态条件,无法满足多线程并发安全要求;第二种所有方法加synchronized的方案可以满足线程安全要求,是更优的选择。


方案1:Volatile+仅原子方法加Synchronized

public class CalcStrategySet {
   private volatile CalcStrategy current;
   private volatile CalcStrategy backup;
   private volatile boolean isBackup;

   public CalcStrategySet(CalcStrategy current, CalcStrategy backup) {
       this.current = current;
       this.backup = backup;
   }

   public void isStandard() {
       return !isBackup;
   }
  
   public void merge(CalcStrategy other) {
      current.merge(other);
   }

   public synchronized void flip() {
      if(!isBackup) {
          current = backup;
          backup = null;
          isBackup = true;
      } else {
          throw new IllegalStateException("Already in backup mode");
      }
   }
}

存在的问题

  • merge方法无同步保护:volatile只能保证current引用本身的可见性,无法保证current.merge(other)内部操作的原子性和可见性。如果CalcStrategy的merge方法本身没有做线程安全处理,多线程同时调用merge修改同一个策略实例的状态时,必然会出现数据错乱。
  • 复合操作存在竞态:如果业务逻辑先调用isStandard()判断当前模式,再执行对应操作,两步操作之间没有锁保护,判断完成后可能被其他线程执行flip切换模式,导致后续操作和判断结果不匹配。
  • flip和merge并发冲突:线程刚读取到current引用还没执行merge操作时,其他线程可能已经执行完flip替换了current指向的实例,最终merge操作落到了已失效的旧策略对象上,不符合业务预期。

方案2:全Synchronized实现

public class CalcStrategySet {
   private CalcStrategy current;
   private CalcStrategy backup;
   private boolean isBackup;

   public CalcStrategySet(CalcStrategy current, CalcStrategy backup) {
       this.current = current;
       this.backup = backup;
   }

   public synchronized void isStandard() {
       return !isBackup;
   }
  
   public synchronized void merge(CalcStrategy other) {
      current.merge(other);
   }

   public synchronized void flip() {
      if(!isBackup) {
          current = backup;
          backup = null;
          isBackup = true;
      } else {
          throw new IllegalStateException("Already in backup mode");
      }
   }
}

合理性说明

所有对外方法都加了synchronized修饰,以当前实例作为锁,保证同一时间只有一个线程执行类中的任意方法,完全规避了竞态问题:

  • 执行merge的过程中flip无法抢占锁执行,不会出现current中途被替换的问题
  • 多线程调用merge时会串行执行,避免了并发修改CalcStrategy状态的问题
  • 不需要额外加volatile修饰成员变量,因为synchronized已经同时保证了操作的原子性、可见性和有序性,所有对成员变量的修改都会同步到主内存,读操作也会从主内存拉取最新值。

可选优化方案

如果读操作(如isStandard)的调用频率远高于写操作(flip、merge),可以用ReentrantReadWriteLock读写锁替代synchronized:读方法加共享读锁,支持多线程并发读;写方法加独占写锁,同一时间只有一个线程执行写操作,相比全synchronized的串行执行效率更高。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 02:09:04