java - 在实例对象上同步
问题描述
我有一个服务方法,它基本上是将记录插入数据库。我想要实现的是基于对象或其变量阻止一段代码。
我需要根据这个 id 阻止其他线程:rcvTransactionRequest.getPoDistributionId()
我不想阻止所有进入这个方法的线程。最后,我试图验证不应超过的应收数量,如果多个线程进入关键部分,可能会发生这种情况。
PoDistPayload poDistPayload = poDistService.getPoDist(rcvTransactionRequest.getPoDistributionId());
synchronized (poDistPayload) {
if (!poDistService.isReceivable(poDistPayload, rcvTransactionRequest.getQuantity()))
throw ebsExceptionFactory.build(1036L, rcvTransactionRequest.getQuantity(), poDistPayload.getReceivableQuantity());
PoDistRcv poDistRcv = PoDistRcv.of(rcvTransactionRequest);
poDistRcv.setStatus(Status.TRANSACTION_STARTED);
poDistRcv = poDistRcvRepository.save(poDistRcv);
return new BaseTransactionResponse(poDistRcv.getTransactionId(), serialCountPerRequest, poDistRcv.getStatus());
}
解决方案
您可以使用 ConcurrentMap 来实现一个简单的锁定方案:
Object newLock=new Object();
Object existingLock;
// Wait until this thread can acquire lock
synchronized(newLock) {
do {
existingLock=cMap.putIfAbsent(distributionId,newLock);
if(existingLock!=null) {
// Locked by another thread. You can fail immediately, or wait until the lock is released
synchronized(existingLock) {
// Need timeout here because lock holder may notify before we wait
existingLock.wait(timeout);
}
}
} while(existingLock!=null);
// You have the lock
// Do work
// Unlock and notify
cMap.remove(distributionId,newLock);
newLock.notify();
}
推荐阅读
- linux - Ansible ec2_vpc_igw VPC 不存在
- grafana - 基于模板变量创建单态面板的动态仪表板
- maven - 使用 Maven 生成 JaCoCo 代码覆盖率报告
- java - 如何创建一个写入数据库内容的rowmapper类返回一个bean类
- python-2.7 - Dict Comprehension - 为什么调试器告诉我我的 dict 是一个集合?
- mongodb - findOne 与 $push 创建重复对象
- html - 从另一个组件以编程方式聚焦输入框
- python - 无法弄清楚如何计算 .wav 文件的光谱特性
- haskell - “‘节点’应用于太少的参数”即使有确切的数字
- sql - 连接表时缺少数据