Java 多个线程一次更新数据库中的同一行如何保持一致性

Java 多个线程一次更新数据库中的同一行如何保持一致性,java,database,multithreading,hibernate,concurrency,Java,Database,Multithreading,Hibernate,Concurrency,在我的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

在我的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 ??  

您的问题不是100%清楚,但我想您正在寻找不同的锁定策略:

有两种可能的方法

  • 要么选择悲观的方法并锁定行、表甚至行的范围

  • 或者使用版本化实体(乐观锁定)

也许您可以在此处找到更多信息:


以这种方式递增计数器很难同时管理。您确实需要使用悲观锁定来解决这个特定问题

SELECT 1 FROM mytable WHERE x IS TRUE FOR UPDATE
这将迫使每个线程在读取计数器之前等待上一个线程提交

这是必要的,因为您有两个潜在问题,第一个是读竞争,第二个是写锁。在大多数RDBMS中,写入锁是自动获取的,但除非在读取之前显式获取,否则计数器将由两个线程一起递增一次(因为两个线程都在更新之前读取原始值)


如果需要并行写入,则需要插入一个表,然后在以后具体化聚合。这是一个更复杂的设计模式。

< P>如果你在一个有序列生成器(Oracle,PoxGres,…)的DB上工作,你应该考虑使用那些。假设您总是执行相同的增量值,并且一个线程的增量为一个线程,另一个线程的增量为两个线程,那么这应该是一个很好的解决方案。

下面是这个问题的详细答案: 总结如下:

最大的问题是:两个线程是否试图持久化相同的数据?总结链接答案的内容。让我们命名两个线程T1和T2。有两种方法:

方法1,这或多或少是上次更新Wins的情况。它或多或少地避免了乐观锁定(版本计数)。如果您没有从T1到T2的依赖关系,或者没有反向依赖关系来设置解析状态。这应该很好

Aproach 2乐观锁定这就是您现在拥有的。解决方案是刷新数据并重新启动操作

一个3行级别的DB锁这里的解决方案与方法2的解决方案大致相同,只是悲观锁进行了一些小的修正。主要区别在于,在这种情况下,它可能是一个读锁,如果是悲观读,您甚至可能无法从数据库中读取数据以刷新它


Aproach 4应用程序级同步有许多不同的同步方法。一个例子是将所有更新实际安排在BlockingQueue或JMS队列中(如果您希望它是持久的),并从单个线程推送所有更新。为了将其可视化,位T1和T2将把元素放在队列上,并且将有一个T3线程读取操作并将它们推送到数据库服务器。

在一个数据库事务中每个线程更新了多少个实体?到目前为止,有一个实体,但可能重复