我测试了在hibernate调用中同时运行两个任务。它错误地创建了两个具有相同案例编号的对象。我想要锁定此方法,直到object1获取其案例编号,然后object2将获得不同的案例编号。
public String getNextCaseNumberFromDatabase(String tenantId) {
LOGGER.entering(getClass().getName(), "getNextCaseNumber");
Configuration caseNumberStartValueConfiguration = null;
List<Case> cases = null;
try {
caseNumberStartValueConfiguration = configurationService.getConfigurationByKey(ConfigurationKey.CASE_NUMBER_START_VALUE, tenantId);
} catch (RuntimeException ex) {
throw ex;
}
try {
cases = caseService.getAllCases(tenantId);
} catch (RuntimeException ex) {
throw ex;
}
//LOCK DATABASE HERE
synchronized(this) {
// Get the largest case number in the database and increment from it
int largestCaseNumber = 0;
for (int i = 0; i < cases.size(); i++) {
if (cases.get(i).getCaseNumber() != null) {
if (Integer.parseInt(cases.get(i).getCaseNumber()) > largestCaseNumber) {
largestCaseNumber = Integer.parseInt(cases.get(i).getCaseNumber());
}
}
}
// Set the case number to either the next largest number or the configured value, whichever is larger
String caseNumber = "1";
if (largestCaseNumber >= Integer.parseInt(caseNumberStartValueConfiguration.getConfigurationValue())) {
caseNumber = Integer.toString(largestCaseNumber + 1);
} else if (caseNumberStartValueConfiguration != null) {
caseNumber = caseNumberStartValueConfiguration.getConfigurationValue();
}
LOGGER.exiting(getClass().getName(), "getNextCaseNumber");
return caseNumber;
}//END LOCK HERE
}
如你所见,我添加了synchronized(this){} 它什么都不做。知道我需要做些什么来正确锁定它吗?我需要锁定整个方法吗?
答案 0 :(得分:1)
以这种方式进行同步
public synchronized String getNextCaseNumberFromDatabase(String tenantId) {
}
与以这种方式进行同步相同
public String getNextCaseNumberFromDatabase(String tenantId) {
syncronized(this) {
}
}
两种情况都使用this
进行同步。正如@MarkTucker所暗示的那样,“这个'在两个线程中是不同的,所以同步没有做任何事情”。您需要一个静态字段来同步它
private static Object sync = new Object();
public String getNextCaseNumberFromDatabase(String tenantId) {
syncronized(sync) {
}
}
但这不是最好的方式。尝试在数据库中只使用一行表示最大案例编号,并在事务中获取下一个案例编号。
开启交易。
获取具有悲观锁定(LockMode.PESSIMISTIC_WRITE
或类似的当前案例编号,它取决于Hibernate
版本)
session.get(CaseNumber.class, caseNumberId, LockMode.PESSIMISTIC_WRITE)
增加案例编号并更新CaseNumber
。
提交交易。
返回递增的案例编号。
其他线程将等待事务提交。