我正在阅读一篇关于jpa锁定的文章。链接:https://blogs.oracle.com/carolmcdonald/entry/jpa_2_0_concurrency_and
在关于乐观锁(READ)的部分中,作者有代码片段,其中说明事务2因异常而被回滚。基于代码片段,事务2在事务1修改dep的名称之前获取dep上的锁。如果我从学校正确理解讲座,从获得锁定(文章中的em.lock)到锁定被释放(文章中的tx2.commit),行动(在文章中将员工提高10%)是原子,这意味着dep的名称不能设置为“MarketEng”,因此,员工获得10%的提升。在tx2提交后,它释放锁定,dep的名称最终设置为“MarketEng”。因此,没有事务被回滚并且它是线程安全的。
我理解正确吗?如果没有,请向我解释一下作者的意思是“e1获得他不配的加薪”。
答案 0 :(得分:0)
乐观锁定有点用词 - 没有实际的锁定。您描述的行为(tx2中的em.lock
将阻止tx1中的更新)是一种悲观锁定。在JPA中,悲观锁转换为DB中具有select .. for update
的行级锁。乐观的锁不会。
乐观锁定使用计数器在对象更新时进行通信,或验证是否发生了更新。写入总是递增计数器。使用LockMode.OPTIMISTIC进行读取将在提交时检查计数器,如果值已更改,则会因异常或回滚而失败。
乐观锁定的一点是你“乐观地”认为在同一个对象实例上的这种冲突在实践中很少见,因此最好冒失败提交,而不是通过实际的行级锁减慢一切,并且担心死锁。
在此特定示例中,有两个并发运行的事务:
但是,这个例子存在一些缺陷,因为从业务或用户的角度来看,影响与直觉不匹配 - 如果tx1在tx2提交后刚刚启动,则部门名称会在员工获得加薪后立即更改。如果名称提前一瞬间改变,为什么重要?
我喜欢使用的类比是版本控制系统。大多数版本控制系统(如svn和git)都使用某种形式的乐观锁定。允许两个人同时在同一个文件上开始工作,但是当您尝试提交其他人首先提交的文件时,您会收到错误。其他版本控制系统,如Visual SourceSafe(至少我最后一次使用它)使用悲观锁定,你必须检查一个文件进行编辑,结账是一个独占锁 - 没有其他人可以检查相同的文件编辑,直到你提交。