Java EE:为什么我们需要了解并发?

时间:2014-09-20 14:08:22

标签: java multithreading hibernate concurrency transactions

我从着名的书籍 - Mastering Enterprise JavaBeans™3.0中提取以下几行。

  

并发访问和锁定:数据库中对数据的并发访问始终受事务隔离的保护,因此您无需设计其他并发控制来保护您的   适当使用事务时应用程序中的数据。除非您制定特定条款,否则您的实体将受到容器管理事务的保护,这些事务使用为持久性提供程序和/或EJB容器的事务服务配置的隔离级别。但是,了解应用程序的并发控制要求和语义非常重要。

然后讨论Java Transaction API,Container Managed和Bean Managed Transaction,不同的TransactionAttributes,不同的Isolation Levels。它还说明了 -

  

Java Persistence规范定义了两个重要的功能   针对同时访问的实体进行了调整:   1.使用版本属性进行优化锁定   2.明确的读写锁定

好的 - 我读了所有内容,并且理解得很好。但问题在于我需要使用所有这些技术的场景?如果我使用容器管理事务,它为我做了一切为什么我需要打扰所有这些细节?我知道TransactionAttributes(REQUIRED,REQUIRES_NEW)的重要性,并知道我需要在哪些情况下使用它们,但其他情况呢?更具体地说 -

  1. 为什么我需要Bean管理事务?
  2. 为什么我们需要对实体类进行读写锁定?
  3. 为什么我们需要版本属性?
  4. 对于Q2和Q3 - 我认为实体类不是线程安全的,因此我们需要锁定那里。但是数据库是由JTA API在EJB类中管理的(如第一段中所述),那么为什么我们需要单独管理实体类?我知道Lock和Version如何工作以及为什么需要它们。但是,既然JTA已经存在,为什么他们会进入画面呢?

    你能否提供任何答案?如果你给我一些URL,即使非常感激。

    非常感谢提前。

1 个答案:

答案 0 :(得分:0)

您不需要锁定,因为实体类不是线程安全的。不得在线程之间共享实体,这就是全部。

您的数据库附带了ACID保证,但这并不总是足够的,您有时需要明确锁定行以获得所需内容。想象一下以下场景:

  • 事务A从数据库中读取员工1
  • 事务B从数据库中读取员工1
  • 交易A将员工1的薪水设为3000
  • 交易B将员工1的薪水设为4000
  • 事务A提交
  • 交易B提交

最终结果是工资是4000.启动事务A的用户完全不知道即使他将薪水设置为3000,另一个用户同时将其设置为4000.根据最后写入的事务,最终结果是不同的(因此是不可预测的)。这是使用乐观锁定可以避免的那种情况。

下一个方案:您希望生成纯粹的顺序发票号,没有丢失值且没有重复。你可以想象在数据库中读取和增加一个值来做到这一点。但是两个事务可能同时读取相同的值,然后递增它。你会因此而重复。使用保存下一个数字的表格行中的锁可以避免这种情况。