如何通过Java中的对象值来同步块

本文探讨了如何在Java中通过对象值进行同步,以解决银行应用程序转账场景中的并发问题。错误的方法包括同步方法和字符串实习,它们可能导致性能下降或同步问题。正确的解决方案是创建自定义同步原语,使用 WeakReference 存储在 ConcurrentHashMap 中,以确保相同值的对象得到正确同步。同时,文章提供了一个名为XSync的库,简化了这一过程,并进行了性能基准测试和并发测试以验证解决方案的有效性。
摘要由CSDN通过智能技术生成

问题

有时,我们需要通过变量的值来同步代码块。

为了解这个问题,我们将考虑一个简单的银行应用程序,它对客户的每次转账进行以下操作:

  1. 通过此外部Web服务转移评估现金返还金额(CashBackService
  2. 在数据库中执行汇款(AccountService
  3. 更新现金返还评估系统中的数据(CashBackService

汇款操作如下:

public  void  withdrawMoney(UUID  userId,int  amountOfMoney){
   
    synchronized(userId){  
        结果 result  =  externalCashBackService。evaluateCashBack(userId,amountOfMoney);
        accountService。转移(用户id,amountOfMoney  +  结果。getCashBackAmount());
        externalCashBackService。cashBackComplete(用户id,结果。getCashBackAmount());
    }
}

 

应用程序的基本组件如下图所示:

应用程序的组件图

我试图尽可能清楚地做出一个例子。支付服务中的资金转移取决于其他两项服​​务:

  • 第一个是CashBackService与REST协议下的另一个(外部)Web应用程序交互。而且,为了计算实际的现金返还,我们需要与此应用程序同步事务。这是因为下一笔现金返还金额可能取决于用户付款总额。
  • 第二个是AccountService与内部数据库通信并存储与其用户帐户相关的数据。在此服务中,我们可以使用JPA事务在数据库中将某些操作作为原子操作。

在现实生活中,我强烈建议重构这样的系统,以避免这种情况,如果可能的话。但在我们的例子中,想象一下我们别无选择。

我们来看看这个应用程序的草案代码:

@服务
公共  PaymentService {
   
 
    @Autowired
    private  ExternalCashBackService  externalCashBackService ;
 
    @Autowired
    私人 AccountService  帐户服务 ;
 
    public  void  withdrawMoney(UUID  userId,int  amountOfMoney){
   
        synchronized(userId){  
            结果 result  =  externalCashBackService。evaluateCashBack(userId,amountOfMoney);
            accountService。转移(用户id,amountOfMoney  +  结果。getCashBackAmount());
            externalCashBackService。cashBackComplete(用户id,结果。getCashBackAmount());
        }
    }
}
 
 
@服务
公共  ExternalCashBackService {
   
 
    @Autowired
    私人 RestTemplate  restTemplate ;
 
    public  Result  evaluateCashBack(UUID  userId,int  amountOfMoney){
   
        return  sendRestRequest(“evaluate”,userId,amountOfMoney);
    }
 
    public  Result  cashBackComplete(UUID  userId,int  cashBackAmount){
   
        return  sendRestRequest(“complete”,userId,cashBackAmount);
    }
 
    private  Result  sendRestRequest(String  action,UUID  userId,int  value){
   
 
        URI  externalCashBackSystemUrl  =
                URI。create(“http://cash-back-system.org/api/”  +  action);
 
        HttpHeaders  headers  =  new  HttpHeaders();
        标题。集(“接受”,的MediaType。APPLICATION_JSON_VALUE);
        RequestDto  requestDto  =  new  RequestDto(userId,value);
        HttpEntity <?>  request  =  new  HttpEntity <>(requestDto,headers);
 
        ResponseDto  responseDto  =  restTemplate。exchange(externalCashBackSystemUrl,
                                                        HttpMethod。GET,
                                                        要求,
                                                        ResponseDto。课程
                                              。getBody();  
 
        返回 新的 结果(responseDto。的getStatus(),responseDto。的getValue());
    }

                
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值