Java MySQL防止竞争条件

时间:2015-12-15 22:27:12

标签: java mysql multithreading prepared-statement race-condition

我编写了一个java应用程序,它启动异步线程来读取和更新同一数据库中的值。每个线程从连接池(c3p0)获取连接。我必须防止竞争条件,因为我必须根据当前值更新条目。因此,使用SELECT语句读取数据然后使用UPDATE语句更新它将导致竞争条件,因此它不是线程安全的。我已经找到了一些如何防止这种竞争条件的解决方案,但我还是有一些问题。

例如,我可以使用那种UPDATE ExampleTable SET ExampleValue = ExampleValue + '5' WHERE Id = '10'来增加线程安全值。我读到这是一个原子声明。所以我的第一个问题是:在java中执行PreparedStatement始终是线程安全的吗?我是这么认为的,因为(如果autoCommit为真)每个执行的语句都是一个事务,事务是原子的,对吧?如果是的话,如果我用一个语句调用一个过程,或者我在一个用分号分隔的语句中放了多个查询,那么情况也是如此吗?

我还读到我可以将autoCommit设置为false并在执行时执行多个语句,这也可以实现线程安全,因为没有其他语句可以中断事务。是吗?

有没有进一步的解决方案来防止这种竞争条件?

1 个答案:

答案 0 :(得分:1)

  

在java中执行PreparedStatement总是线程安全吗?

我不确定这意味着什么。您只能在单个帖子中使用PreparedStatement及其基础Connection,因此不会出现此问题。

  

我是这么认为的,因为(如果autoCommit为true)每个执行的语句都是一个事务,事务是原子的,对吧?如果是的话,如果我用一个语句调用一个过程,或者我在一个用分号分隔的语句中放了多个查询,那么情况也是如此吗?

我是这么认为的。您真正要问的是PreparedStatement atomic,是否跨线程或进程,除非您使用自动提交,否则答案为“否”。如果您正在使用事务,则它是原子事务。 [事实上,它始终是原子的事务,但在自动提交模式下,它与语句共同扩展。]

  

我还读到我可以将autoCommit设置为false并在执行时执行多个语句,这也可以实现线程安全,因为没有其他语句可以中断事务。是吗?

它实现原子性。线程安全完全是另一回事。

在非自动提交的交易中,您可能正在寻找的是SELECT... FOR UPDATE。它会锁定返回的行,以便在提交此事务之前,它们不能由另一个此类语句返回。或者像INSERT ... ON DUPLICATE KEY [IGNORE|UPDATE]

这样的结构