Java MySQL 防止竞争条件

Java MySQL prevent race condition

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

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

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

是否有任何进一步的解决方案来防止此类竞争条件?

Is executing a PreparedStatement in java always thread safe?

我不确定这是什么意思。您只会在单个线程中使用 PreparedStatement 及其基础 Connection,因此不会出现此问题。

I think so because (if autoCommit is true) every single executed statement is a transaction and transactions are atomic, right? If yes, is that also the case if I call a procedure with a statement or if I put multiple queries in one statement separated through semicolons?

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

I also read that I can set autoCommit to false and execute multiple statements befor commiting, wich also achieves thread safety because no other statement can interrupt a transaction. Is that right?

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

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

这样的结构