在我的java应用程序中,多个线程一次更新同一行如何获得一致性结果?
例如
current row value count =0;
thread 1 updating it to count+1=1;
thread 2 updating at the same time count+1=2
but it should not happen like this
thread 1 updating it to count+1=1;
thread 2 updating at the same time count+1=1;
both threads should not catch the same value because both are running same time
how can we achieve this in jdbc hibernate , database ??
答案 0 :(得分:2)
有两种可能的方法。
您可以选择悲观方法并锁定行,表甚至行范围。
或者您使用版本化的实体(乐观锁定)。
也许你可以在这里找到更多信息:
https://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html
答案 1 :(得分:1)
以这种方式增加计数器很难同时管理。你真的需要使用悲观锁定来解决这个特殊问题。
SELECT 1 FROM mytable WHERE x IS TRUE FOR UPDATE
这将强制每个线程等到上一个线程在读取计数器之前提交。
这是必要的,因为你有两个潜在的问题,第一个是读比赛,第二个是写锁。写锁定在大多数RDBMS中自动获取,但除非您在读取之前明确地使用它,否则计数器将由两个线程一起一次递增(因为两者都在更新之前读取原始值)。
如果需要进行并行写入,则需要插入表,然后再实现聚合。这是一个更复杂的设计模式。
答案 2 :(得分:0)
您的问题并非100%明确,但我猜您正在寻找不同的锁定策略:http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#locking
答案 3 :(得分:0)
如果您正在使用具有序列生成器的数据库(Oracle,Postgres,...),您应该考虑使用它们。假设你总是做同样的增量值,并且不是一个线程增加一个而另一个增加两个,那么这应该是一个很好的解决方案。
答案 4 :(得分:0)
以下是此问题的详细答案: How to properly handle two threads updating the same row in a database 总结一下:
最大的问题是:这两个线程是否试图保留相同的数据?总结链接答案的内容。让我们命名两个线程T1和T2。有几个方法:
方法1 ,这或多或少是最后一次更新“获胜”的情况。它或多或少避免了乐观锁定(版本计数)。如果您没有从T1到T2的依赖关系,或者为了设置状态PARSED而没有依赖关系。这样应该很好。
Aproach 2乐观锁定,这就是您现在拥有的。解决方案是刷新数据并重新开始操作。
方法3行级DB锁此处的解决方案与方法2大致相同,只是悲观锁所造成的微小修正。主要区别在于,在这种情况下,它可能是READ锁,并且如果是PESSIMISTIC READ,您甚至可能无法从数据库中读取数据以刷新它。
Aproach 4应用程序级同步。有许多不同的同步方法。一个示例是将所有更新实际安排在BlockingQueue或JMS队列中(如果您希望它是持久的),然后从单个线程推送所有更新。为了使它形象化,T1和T2会将元素放入队列,并且只有一个T3线程读取操作并将其推送到数据库服务器。