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

ConcurrentHashMap多线程场景下按值字段查询并安全插入方案问询

多线程下ConcurrentHashMap的线程安全实现:按值字段检查并插入

首先明确需求:根据给定的Object key(对应Record的a字段),查找是否存在匹配的Record,存在则返回对应的code(即Record的b字段,也是原Map的key);不存在则生成新code,插入ConcurrentHashMap后返回。原代码存在明显线程安全问题,具体问题如下:

原代码的线程安全隐患

  • 遍历与插入非原子:多个线程可能同时遍历entrySet都未找到匹配的Record,随后各自生成code并插入,导致同一个a字段对应多个code,数据重复。
  • 弱一致性遍历:ConcurrentHashMap的entrySet遍历是弱一致性的,遍历过程中其他线程的插入操作可能无法被当前遍历感知,导致漏查。

线程安全的实现方案

核心思路是利用ConcurrentHashMap的原子方法computeIfAbsent,同时维护一个以Record.a为key的映射,确保检查与插入操作的原子性。

实现代码

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

record Record(Object a, int b) {}

public class SafeRecordStore {
    // 维护a字段到code的映射,用于快速查找
    private final ConcurrentHashMap<Object, Integer> aToCodeMap = new ConcurrentHashMap<>();
    // 维护code到Record的映射,保留原业务的Map结构需求
    private final ConcurrentHashMap<Integer, Record> codeToRecordMap = new ConcurrentHashMap<>();
    // 原子生成唯一code,避免重复冲突
    private final AtomicInteger codeGenerator = new AtomicInteger(0);

    public int get(Object key) {
        // 先尝试从aToCodeMap快速查找
        Integer existingCode = aToCodeMap.get(key);
        if (existingCode != null) {
            return existingCode;
        }

        // 原子化操作:仅当key不存在时,执行生成与插入逻辑
        return aToCodeMap.computeIfAbsent(key, k -> {
            int newCode = generateUniqueCode();
            codeToRecordMap.put(newCode, new Record(k, newCode));
            return newCode;
        });
    }

    // 生成全局唯一的code,可根据业务需求调整规则
    private int generateUniqueCode() {
        return codeGenerator.getAndIncrement();
    }
}

关键说明

  • 双Map维护:aToCodeMap负责快速根据a字段查找code,避免全量遍历;codeToRecordMap保留原业务的Map结构,满足按code查找Record的需求。
  • 原子性保证:computeIfAbsent是ConcurrentHashMap的原子方法,多个线程同时调用时,只有一个线程会执行lambda中的生成与插入逻辑,其他线程会直接返回已生成的结果,避免重复插入。
  • 唯一code生成:使用AtomicInteger生成自增的code,确保全局唯一,避免与已有code冲突。

简化版实现(如果不需要按code查Record)

如果业务中不需要维护code到Record的映射,可直接将a字段作为ConcurrentHashMap的key,进一步简化代码:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

record Record(Object a, int b) {}

public class SimplifiedSafeStore {
    private final ConcurrentHashMap<Object, Record> aToRecordMap = new ConcurrentHashMap<>();
    private final AtomicInteger codeGenerator = new AtomicInteger(0);

    public int get(Object key) {
        Record record = aToRecordMap.computeIfAbsent(key, k -> {
            int newCode = codeGenerator.getAndIncrement();
            return new Record(k, newCode);
        });
        return record.b();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 20:00:47