【问题标题】:Atomically update 2 Long values以原子方式更新 2 个 Long 值
【发布时间】:2020-08-27 18:38:34
【问题描述】:

假设我在 Java 中有以下类:

class Record {
  
  String name;
  double count;
  long repeat;
  
  public Record(String name){
    this.name = name;
  }

  public synchronized void update(Record other){
    this.count = (other.count * other.repeat + this.count * this.repeat)/(other.repeat + this.repeat);
    this.repeat = this.repeat + other.repeat;
  }

现在我有一张此类记录的地图ConcurrentHashMap<String, Record> recordConcurrentHashMap;

我想创建一个线程安全的正确更新函数。

目前我已经这样做了:

static ConcurrentHashMap<String,Record> recordConcurrentHashMap;

public static void updateRecords(Record other){
    Record record = recordConcurrentHashMap.computeIfAbsent(other.name, Record::new);
    record.update(other);
}

我必须保持update 函数同步以实现正确性。

如果不使用synchronized,我可以使用LongAdderLongAccumulator 执行此操作吗?

我尝试使用这些,但不知道如何使用它们实现复杂的计算。

【问题讨论】:

    标签: java multithreading atomic atomicinteger


    【解决方案1】:

    不,你不能,当然不是那些。

    你可能会考虑做的——这将避免synchronized——将是使Record不可变和不可修改,并做类似的事情

    class Record {
      final String name;
      final double count;
      final long repeat;
    
      public Record(String name){
        this.name = name;
      }
    
      private Record(String name, double count, long repeat) {
        this.name = name; this.count = count; this.repeat = repeat;
      }
    
      public Record combine(Record other){
        return new Record(
          name,
          other.count * other.repeat + this.count * this.repeat)
             /(other.repeat + this.repeat),
          repeat + other.repeat);
      }
    }
    
    public static void updateRecords(Record other){
      Record record = recordConcurrentHashMap.merge(
        other.name, other, Record::combine);
    }
    

    【讨论】:

    • 它是否必须是不可变的,因为合并是原子的?不能合并调用组合并返回更新的记录之一以占用地图值?不能重复使用其他记录吗?
    • 是的,它确实需要是不可变的;否则同一记录上的多个合并可能会竞争甚至导致无意义的输出——在没有锁的情况下,关键是要消除它。 (请注意,例如,merge 可能会在发生争用时多次调用该方法,因此您最终可能会将这些值组合两次!)
    猜你喜欢
    • 2021-05-28
    • 2013-04-17
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 2018-03-02
    • 1970-01-01
    相关资源
    最近更新 更多