基于实体ID的Java ReentrantLock同实体更新互斥实现需求
基于实体ID的可重入锁实现方案
你需要的是按实体ID维度隔离的锁管理器,核心思路是用并发容器维护每个ID对应的可重入锁,保证同一ID的操作互斥,不同ID的操作并行。以下是具体实现:
1. 锁管理器核心实现
创建单例锁管理类,用ConcurrentHashMap存储实体ID与锁的映射,同时通过引用计数避免内存泄漏:
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.ReentrantLock; public class EntityLockManager { private static final EntityLockManager INSTANCE = new EntityLockManager(); private final ConcurrentHashMap<String, LockWrapper> lockMap = new ConcurrentHashMap<>(); private EntityLockManager() {} public static EntityLockManager getInstance() { return INSTANCE; } // 获取对应实体ID的锁 public ReentrantLock getLock(String entityId) { lockMap.compute(entityId, (id, wrapper) -> { if (wrapper == null) { return new LockWrapper(new ReentrantLock()); } wrapper.incrementRefCount(); return wrapper; }); return lockMap.get(entityId).lock; } // 释放对应实体ID的锁 public void releaseLock(String entityId) { lockMap.computeIfPresent(entityId, (id, wrapper) -> { wrapper.decrementRefCount(); return wrapper.getRefCount() == 0 ? null : wrapper; }); } // 内部类:封装锁和引用计数 private static class LockWrapper { private final ReentrantLock lock; private int refCount; public LockWrapper(ReentrantLock lock) { this.lock = lock; this.refCount = 1; } public void incrementRefCount() { refCount++; } public void decrementRefCount() { refCount--; } public int getRefCount() { return refCount; } } }
2. 业务代码中的使用方式
在批量更新逻辑中,捕获OptimisticLockException后,获取对应ID的锁并重试操作:
public void updateEntity(String entityId, Entity entity) { boolean success = false; while (!success) { try { // 先尝试乐观锁更新 entityRepository.save(entity); success = true; } catch (OptimisticLockException e) { // 乐观锁冲突时,获取对应ID的锁 ReentrantLock lock = EntityLockManager.getInstance().getLock(entityId); try { lock.lock(); // 加锁后查询实体最新状态,执行更新 Entity latestEntity = entityRepository.findById(entityId).orElseThrow(); mergeEntityUpdates(latestEntity, entity); entityRepository.save(latestEntity); success = true; } finally { lock.unlock(); EntityLockManager.getInstance().releaseLock(entityId); } } } } // 合并实体更新逻辑(根据业务调整) private void mergeEntityUpdates(Entity target, Entity source) { target.setField1(source.getField1()); target.setField2(source.getField2()); // 其他字段更新... }
关键注意事项
- 重入性支持:基于
ReentrantLock,同一线程多次获取同一ID的锁不会阻塞,适配嵌套调用场景。 - 内存泄漏防护:通过引用计数,当某ID的所有锁释放后,会从容器中移除对应条目,避免长期占用内存。
- 性能优化:仅在乐观锁冲突时加锁,无冲突的更新仍可并行执行,不影响批量处理效率。
- 锁粒度精准:严格按实体ID隔离,不同ID的操作完全并行,最大化利用系统资源。
内容的提问来源于stack exchange,提问作者Cliser
相关产品推荐
相关产品推荐

