我有一个从控制器方法调用的同步方法。 当两个请求访问时,只有一个应该通过,其他应该被阻止,直到第一个完成。
但是当传入的请求很快时,这实际上是将同一个accountId返回给两个不同的请求,这不是预期的。
请帮助我了解如何同步此getNextAccount()调用,以便它只将一个帐户返回到一个请求。
AccService.java中的方法
private final Object lockObject = new Object();
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Long getNextAccount(String hostport) {
synchronized (lockObject) {
Long acc = null;
try {
AccountFetch dtls = getAccount();
if (dtls != null) {
acc = dtls.getAccId();
//Set IN_PROGRESS
dtls.setStatus("Progress");
dtls.saveAndFlush(dtls);
return acc;
} else {
log.info("No More Accounts to Process");
}
} catch (Exception e) {
e.getStackTrace();
}
return acc;
}
}
@Autowired
private AccService accSevice;
@GET
@Path("/accprocess")
@Produces(MediaType.APPLICATION_JSON)
public AccountFetch getAccId(@QueryParam("currentHost") final String currentHost,
@QueryParam("currentPort") final String currentPort) {
AccountFetch dtls = new AccountFetch();
try {
Long batchId = accSevice. getNextAccount(currentHost+"#"+currentPort);
if (accId != null) {
dtls.setAccId(String.valueOf(accId));
} else {
dtls.setAccId(BLANK_STRING);
}
} catch (Exception e) {
log.error("Exception while getting accId : " + e.getMessage());
}
return dtls;
}
public AccountFetch getAccount(){...}
答案 0 :(得分:1)
如果线程在同一主机上,并且它们使用相同的锁定对象锁定,则synchronized
块仅允许您互斥。
根据您最初在问题中所写的内容,似乎不满足这些先决条件中的一个或两个。如果(现在发现)只有一个主机处理这些请求,那么我们必须考虑另一种可能性;即有AccService
个对象处理请求的多个实例。
同步也可能有效,问题出在其他地方。例如,getAccount()
可能会在后续调用中返回相同的帐户。
基本上,您的代码库中有太多部分我们无法看到。这意味着我们只能理解造成问题的原因。如果每件事都做得恰到好处;即
getAccount()
已正确实施,getAccount
在没有正确同步的情况下使用的帐户状态然后您向我们展示的代码将工作。
如果您需要更多帮助,可能需要MCVE。