【发布时间】:2018-07-09 08:22:02
【问题描述】:
我正在尝试在 spring 控制器中使用同步方法。因为我们的支付网关一次点击方法 [@RequestMapping(value="/pay",method=RequestMethod.POST)] 不同的交易 [txn id : txn01 & txn02]。但是由于使用了同步块,这两个不同的事务处理是一一处理而不是并行处理。
问题 -> 为什么我在控制器中使用同步块是说事务 [txn01] 命中 [@RequestMapping(value="/pay",method=RequestMethod.POST)] 两次,就像来自支付网关的重复调用一样。在完成第一次调用 [后端处理] 之前,我从支付网关收到第二次调用相同的 tran id。
除了重复调用之外,有什么方法可以在同步块中使用事务 ID 并行处理两个不同的事务,我的意思是相同的事务 ID。请给我建议。
如果我的问题不清楚,请告诉我。
@RequestMapping(value="/pay",method=RequestMethod.POST)
public String payAck(HttpServletRequest httpRequest,HttpServletResponse httpResponse,HttpSession session){
synchronized (this) {
return this.processPayAck(httpRequest, httpResponse, session);
}
}
public synchronized String processPayAck(HttpServletRequest httpRequest,HttpServletResponse httpResponse,HttpSession session){
// Payment Acknowledgment process here
if (sametranIDNotExists) {
// first call here
callWS(); - processing business logic.
return someURL;
} else {
// Gets second call here before first call completed
return someURL;
}
}
修改后的代码:
在同步块中使用实习生的方法是否正确。
@RequestMapping(value="/pay",method=RequestMethod.POST)
public String payAck(HttpServletRequest httpRequest,HttpServletResponse httpResponse,HttpSession session){
String tranID = httpRequest.getParameter("tranID");
synchronized (String.valueOf(tranID).intern()) {
return processPayAck(httpRequest, httpResponse, session);
}
}
【问题讨论】:
-
你的问题很不清楚。我不明白您为什么要尝试同步(您不应该这样做),而且您似乎也不了解同步的工作原理(该方法已经同步,因此同步对该方法的调用是无用的) .因此,您似乎正在尝试随机解决方案来解决不清楚的问题。请记住,即使这样可以解决问题,只要您拥有两台服务器而不是一台,它就不会再解决问题了。您的并发问题可能应该在数据库层处理(使用锁)
-
如果
txn01多次点击/pay,你不会通过同步删除重复的调用,你会将它们排成一个队列——它们都会通过这个方法跨度> -
@Andrew.. 如果 txn01 多次命中,它应该可以在队列中。但是对于不同的交易 txn01 & txn02 它将是并行的
-
@JB Nizet.. 无法在数据库级别处理,因为我使用的是外部 Web 服务。这就是为什么我使用同步来避免重复调用,但它会影响不同的事务。
标签: java multithreading spring-mvc synchronized