gpt4 book ai didi

Java方法同步和数据库读写

转载 作者:搜寻专家 更新时间:2023-11-01 03:31:56 25 4
gpt4 key购买 nike

我有以下读取和写入数据库的方法。它会检查用户数是否少于 MAX_USERS,然后添加一个新用户。

addUser(User user){
//count number of users in the DB, SELECT count(*) from user_table
count = ...

if(count<MAX_USERS){
//add the new user to the DB, INSERT INTO users_table
}
}

这里的问题是,如果上面的代码被多个线程调用,那么它们可能会得到相同的计数值。这将导致 users_table 中的条目超过 MAX_USERS 个。

一种解决方案是同步整个方法,但这会影响性能。有更好的方法来处理这个问题吗?

最佳答案

所有其他答案(synchronized 方法除外)都受制于竞争条件:

如果两个这样的 INSERT 语句同时运行,检查行数的子查询都将发现计数不超过最大值,并且两个 INSERT 语句将插入它们的行,可能会使用户数超出最大值。

使用 AFTER INSERT ON user_table 触发器的解决方案会遇到同样的问题,因为在提交事务之前事务的影响对并发事务不可见。

唯一的防弹解决方案是在数据库中使用SERIALIZABLE 事务:

import java.sql.Connection;
import java.sql.SQLException;

Connection conn;

...

conn.setAutoCommit(false);

boolean transaction_done = false;

while (! transaction_done) {
try {
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

// run the SELECT statement that counts the rows

if (count < MAX_USERS) {
//add the new user to the DB, INSERT INTO users_table
}

conn.commit();

transaction_done = true;
} catch (SQLException e) {
// only retry the transaction if it is a serialization error
if (! "40001".equals(e.getSQLState()))
throw e;
}
}

只有当所有将用户插入表的事务都使用这段代码(或至少使用可序列化的事务)时,这才会起作用。

关于Java方法同步和数据库读写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49166266/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com