【问题标题】:Concurrency issue in a simple Java service简单 Java 服务中的并发问题
【发布时间】:2020-05-15 10:29:00
【问题描述】:
  1. 在下面的 Java ToolHireService 中,我如何以最佳方式防止同一工具可以被多个客户雇用的并发问题。只有在评估租用同一工具时,它才应该“阻塞线程”。

  2. 任何关于如何编写失败测试的指针?

public class ToolHireService {

    public int toolHire(Client client , String toolId , Date startDate , Date endDate){

        Tool tool = getToolFromDB(toolId);

        if(tool == null || tool.isHired()){
            return -1;
        }
        ToolHireEntry toolEntry = new ToolHireEntry(tool,startDate,endDate);
        client.addHireHistory(toolEntry);
        client.save();

        tool.setHired(true);
        return tool.save();

    }
}

PS:只要使用不同的工具,预订就应该能够不间断地进行。

【问题讨论】:

  • 嗯,这里有很多答案。在初步查看您的代码后,我会synchronized 整个方法。还有很多其他的技术。就像在该项目或整个表上添加数据库锁,使用事务。您可以使用休眠并进行乐观锁定。
  • 附带说明,我不会返回调用代码必须检查的成功或失败值。如果无法租用该工具,我会抛出异常。它将减少调用代码对 toolHire 方法内部的依赖。
  • 有没有办法避免同步整个方法,只要使用不同的工具,预订就可以不间断地进行。
  • 答案是肯定的,但它需要使用数据库事务和表/行锁或乐观锁。在我们的团队中,我们使用 Springs @Transactional 注解和 Hibernate 的 Optimistic Locking 策略来完成此类工作。

标签: java multithreading concurrency thread-safety locking


【解决方案1】:

答案一如既往,视情况而定。

您在一个进程中是否有多个客户端正在使用的单个 ToolHireInstance?在这种情况下,只需同步整个方法就足够了。

您在一个进程中是否有多个 ToolHireInstances 供多个客户端使用?在这种情况下,您可以在 ToolHireService.class 对象上进行同步,这将创建一个所有实例都将用于同步的对象。

您是否有多个 ToolHireInstances 分布在多个进程中,每个进程都有客户端(并且您的数据库具有 JDBC 连接器)?在这种情况下,您可能希望通过使整个方法存在于 SQL 事务中来将事务部分推送到 JDBC。这将需要重新组织您的代码以公开事务元素。您需要确定执行此原子 pull_tool->evaluate_status->save_hiring_decision 所需的 SQL 隔离级别。

您是否有多个 ToolHireInstances 分布在多个进程中,每个进程都有客户端(并且没有 JDBC 连接器)?请查阅您的数据库以了解存在何种交易方法。如果不存在,则需要使用其他类型的外部同步工具。

【讨论】:

  • 谢谢,约翰。我只在存在可以由不同线程调用的工具租用服务的单个实例的情况下查看核心 java 选项。此外,我现在已经澄清了上下文,通过添加“只要使用不同的工具,预订就应该能够不间断地进行”来帮助关注这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-17
  • 1970-01-01
  • 2010-10-21
  • 2011-04-08
  • 1970-01-01
相关资源
最近更新 更多