锁定Java任务

时间:2016-01-20 19:48:45

标签: java hibernate synchronization locking

我测试了在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){} 它什么都不做。知道我需要做些什么来正确锁定它吗?我需要锁定整个方法吗?

1 个答案:

答案 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) {

        }    
    }

但这不是最好的方式。尝试在数据库中只使用一行表示最大案例编号,并在事务中获取下一个案例编号。

  1. 开启交易。

  2. 获取具有悲观锁定(LockMode.PESSIMISTIC_WRITE或类似的当前案例编号,它取决于Hibernate 版本)

    session.get(CaseNumber.class, caseNumberId, LockMode.PESSIMISTIC_WRITE)

  3. 增加案例编号并更新CaseNumber

  4. 提交交易。

  5. 返回递增的案例编号。

  6. 其他线程将等待事务提交。