gpt4 book ai didi

Java MySQL死锁(多线程)

转载 作者:行者123 更新时间:2023-11-29 12:55:39 25 4
gpt4 key购买 nike

我遇到了这个奇怪的死锁,但我不太明白为什么会发生

如果两个线程几乎同时调用此方法,我会收到此异常:

java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction

这就是方法

public void saveItems(List<Pair<Item, MapleInventoryType>> items, int id) throws             SQLException {
synchronized (this) {
PreparedStatement ps = null;
PreparedStatement pse = null;
try {
StringBuilder query = new StringBuilder();
query.append("DELETE FROM `inventoryitems` WHERE `type` = ? AND `");
query.append(account ? "accountid" : "characterid").append("` = ?");
Connection con = DatabaseConnection.getConnection();
ps = con.prepareStatement(query.toString());
ps.setInt(1, value);
ps.setInt(2, id);
ps.executeUpdate(); //DEADLOCK OCCURS HERE
ps.close();

for (Pair<Item, MapleInventoryType> pair : items) {
Item item = pair.getLeft();
MapleInventoryType mit = pair.getRight();
ps = con.prepareStatement("INSERT INTO `inventoryitems` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, value);
ps.setString(2, account ? null : String.valueOf(id));
ps.setString(3, account ? String.valueOf(id) : null);
ps.setInt(4, item.getItemId());
ps.setInt(5, mit.getType());
ps.setInt(6, item.getPosition());
ps.setInt(7, item.getQuantity());
ps.setString(8, item.getOwner());
ps.setInt(9, item.getPetId());
ps.setInt(10, item.getFlag());
ps.setLong(11, item.getExpiration());
ps.setString(12, item.getGiftFrom());
ps.executeUpdate();

if (mit.equals(MapleInventoryType.EQUIP) || mit.equals(MapleInventoryType.EQUIPPED)) {
pse = con.prepareStatement("INSERT INTO `inventoryequipment` VALUES (DEFAULT, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
try (ResultSet rs = ps.getGeneratedKeys()) {

if (!rs.next()) {
throw new RuntimeException("Inserting item failed.");
}

pse.setInt(1, rs.getInt(1));
}
ps.close();

Equip equip = (Equip) item;
pse.setInt(2, equip.getUpgradeSlots());
pse.setInt(3, equip.getLevel());
pse.setInt(4, equip.getStr());
pse.setInt(5, equip.getDex());
pse.setInt(6, equip.getInt());
pse.setInt(7, equip.getLuk());
pse.setInt(8, equip.getHp());
pse.setInt(9, equip.getMp());
pse.setInt(10, equip.getWatk());
pse.setInt(11, equip.getMatk());
pse.setInt(12, equip.getWdef());
pse.setInt(13, equip.getMdef());
pse.setInt(14, equip.getAcc());
pse.setInt(15, equip.getAvoid());
pse.setInt(16, equip.getHands());
pse.setInt(17, equip.getSpeed());
pse.setInt(18, equip.getJump());
pse.setInt(19, 0);
pse.setInt(20, equip.getVicious());
pse.setInt(21, equip.getItemLevel());
pse.setInt(22, equip.getItemExp());
pse.setInt(23, equip.getRingId());
pse.executeUpdate();
pse.close();
}
}
} finally {
if (ps != null) {
ps.close();
}
if (pse != null) {
pse.close();
}
}
}

我不明白死锁是如何发生的,因为所有内容都包含在同步块(synchronized block)内。

非常感谢您的帮助,谢谢。

最佳答案

检查您的事务隔离级别。

您是否将 autoCommit() 设置为 false ?如果为 true,那么当您在事务上下文中运行时,您需要在工作后提交它,因为,如果您的事务隔离级别强为可重复读取,那么锁定将在 Activity 事务的上下文上,直到提交发生。

向我们提供有关您正在做什么的更多详细信息。

关于Java MySQL死锁(多线程),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24091897/

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