死锁预防(Java+MySQL)

发布于 2024-12-07 05:00:30 字数 6121 浏览 0 评论 0原文

我有一个 sql 类,它连接到数据库并更新游戏服务器中的信息。我想知道这里是否会导致死锁以及防止死锁的好方法是什么。我对很多事情都很陌生,所以任何建议都会很棒:)

package server.util;

import java.sql.*;
import java.security.MessageDigest;

import server.model.players.Client;

public class SQL {

public static Connection con = null;
public static Statement stmt;
public static boolean connectionMade;
public static void createConnection() {
    try {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        con = DriverManager.getConnection("jdbc:mysql://URL/DATABASE", "USERNAME", "PASS");
        stmt = con.createStatement();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static ResultSet query(String s) throws SQLException {
    try {
        if (s.toLowerCase().startsWith("select")) {
            ResultSet rs = stmt.executeQuery(s);
            return rs;
        } else {
            stmt.executeUpdate(s);
        }
        return null;
    } catch (Exception e) {
        destroyConnection();
        createConnection();
        e.printStackTrace();
    }
    return null;
}

public static void destroyConnection() {
    try {
        stmt.close();
        con.close();
        connectionMade = false;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static boolean saveHighScore(Client clientToSave) {
    try {
        query("DELETE FROM `skills` WHERE playerName = '"+clientToSave.playerName+"';");
        query("DELETE FROM `skillsoverall` WHERE playerName = '"+clientToSave.playerName+"';");
        //query("DELETE FROM `scores` WHERE playerName = '"+clientToSave.playerName+"';");
        query("INSERT INTO `skills` (`playerName`,`Attacklvl`,`Attackxp`,`Defencelvl`,`Defencexp`,`Strengthlvl`,`Strengthxp`,`Hitpointslvl`,`Hitpointsxp`,`Rangelvl`,`Rangexp`,`Prayerlvl`,`Prayerxp`,`Magiclvl`,`Magicxp`,`Cookinglvl`,`Cookingxp`,`Woodcuttinglvl`,`Woodcuttingxp`,`Fletchinglvl`,`Fletchingxp`,`Fishinglvl`,`Fishingxp`,`Firemakinglvl`,`Firemakingxp`,`Craftinglvl`,`Craftingxp`,`Smithinglvl`,`Smithingxp`,`Mininglvl`,`Miningxp`,`Herblorelvl`,`Herblorexp`,`Agilitylvl`,`Agilityxp`,`Thievinglvl`,`Thievingxp`,`Slayerlvl`,`Slayerxp`,`Farminglvl`,`Farmingxp`,`Runecraftlvl`,`Runecraftxp`,`Hunterlvl`,`Hunterxp`,`Summonlvl`,`Summonxp`) VALUES ('"+clientToSave.playerName+"',"+clientToSave.playerLevel[0]+","+clientToSave.playerXP[0]+","+clientToSave.playerLevel[1]+","+clientToSave.playerXP[1]+","+clientToSave.playerLevel[2]+","+clientToSave.playerXP[2]+","+clientToSave.playerLevel[3]+","+clientToSave.playerXP[3]+","+clientToSave.playerLevel[4]+","+clientToSave.playerXP[4]+","+clientToSave.playerLevel[5]+","+clientToSave.playerXP[5]+","+clientToSave.playerLevel[6]+","+clientToSave.playerXP[6]+","+clientToSave.playerLevel[7]+","+clientToSave.playerXP[7]+","+clientToSave.playerLevel[8]+","+clientToSave.playerXP[8]+","+clientToSave.playerLevel[9]+","+clientToSave.playerXP[9]+","+clientToSave.playerLevel[10]+","+clientToSave.playerXP[10]+","+clientToSave.playerLevel[11]+","+clientToSave.playerXP[11]+","+clientToSave.playerLevel[12]+","+clientToSave.playerXP[12]+","+clientToSave.playerLevel[13]+","+clientToSave.playerXP[13]+","+clientToSave.playerLevel[14]+","+clientToSave.playerXP[14]+","+clientToSave.playerLevel[15]+","+clientToSave.playerXP[15]+","+clientToSave.playerLevel[16]+","+clientToSave.playerXP[16]+","+clientToSave.playerLevel[17]+","+clientToSave.playerXP[17]+","+clientToSave.playerLevel[18]+","+clientToSave.playerXP[18]+","+clientToSave.playerLevel[19]+","+clientToSave.playerXP[19]+","+clientToSave.playerLevel[20]+","+clientToSave.playerXP[20]+","+clientToSave.playerLevel[21]+","+clientToSave.playerXP[21]+","+clientToSave.playerLevel[22]+","+clientToSave.playerXP[22]+");");
        query("INSERT INTO `skillsoverall` (`playerName`,`lvl`,`xp`) VALUES ('"+clientToSave.playerName+"',"+(clientToSave.getLevelForXP(clientToSave.playerXP[0]) + clientToSave.getLevelForXP(clientToSave.playerXP[1]) + clientToSave.getLevelForXP(clientToSave.playerXP[2]) + clientToSave.getLevelForXP(clientToSave.playerXP[3]) + clientToSave.getLevelForXP(clientToSave.playerXP[4]) + clientToSave.getLevelForXP(clientToSave.playerXP[5]) + clientToSave.getLevelForXP(clientToSave.playerXP[6]) + clientToSave.getLevelForXP(clientToSave.playerXP[7]) + clientToSave.getLevelForXP(clientToSave.playerXP[8]) + clientToSave.getLevelForXP(clientToSave.playerXP[9]) + clientToSave.getLevelForXP(clientToSave.playerXP[10]) + clientToSave.getLevelForXP(clientToSave.playerXP[11]) + clientToSave.getLevelForXP(clientToSave.playerXP[12]) + clientToSave.getLevelForXP(clientToSave.playerXP[13]) + clientToSave.getLevelForXP(clientToSave.playerXP[14]) + clientToSave.getLevelForXP(clientToSave.playerXP[15]) + clientToSave.getLevelForXP(clientToSave.playerXP[16]) + clientToSave.getLevelForXP(clientToSave.playerXP[17]) + clientToSave.getLevelForXP(clientToSave.playerXP[18]) + clientToSave.getLevelForXP(clientToSave.playerXP[19]) + clientToSave.getLevelForXP(clientToSave.playerXP[20]) + clientToSave.getLevelForXP(clientToSave.playerXP[21]) + clientToSave.getLevelForXP(clientToSave.playerXP[22]))+","+((clientToSave.playerXP[0]) + (clientToSave.playerXP[1]) + (clientToSave.playerXP[2]) + (clientToSave.playerXP[3]) + (clientToSave.playerXP[4]) + (clientToSave.playerXP[5]) + (clientToSave.playerXP[6]) + (clientToSave.playerXP[7]) + (clientToSave.playerXP[8]) + (clientToSave.playerXP[9]) + (clientToSave.playerXP[10]) + (clientToSave.playerXP[11]) + (clientToSave.playerXP[12]) + (clientToSave.playerXP[13]) + (clientToSave.playerXP[14]) + (clientToSave.playerXP[15]) + (clientToSave.playerXP[16]) + (clientToSave.playerXP[17]) + (clientToSave.playerXP[18]) + (clientToSave.playerXP[19]) + (clientToSave.playerXP[20]) + (clientToSave.playerXP[21]) + (clientToSave.playerXP[22]))+");");
        //query("INSERT INTO `scores` (`playerName`,`killcount`,`pkpoints`,`pcpoints`) VALUES ('"+clientToSave.playerName+"',"+clientToSave.KC+","+clientToSave.pkPoints+","+clientToSave.pcPoints+");");
        } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    return true;
}
}

i have an sql class that connects to the database and updates the information from my game server. I was wondering if anything here would cause a deadlock and what are good ways to prevent deadlocks. I am new to alot of things so any tips would be great :)

package server.util;

import java.sql.*;
import java.security.MessageDigest;

import server.model.players.Client;

public class SQL {

public static Connection con = null;
public static Statement stmt;
public static boolean connectionMade;
public static void createConnection() {
    try {
        Class.forName("com.mysql.jdbc.Driver").newInstance();
        con = DriverManager.getConnection("jdbc:mysql://URL/DATABASE", "USERNAME", "PASS");
        stmt = con.createStatement();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public static ResultSet query(String s) throws SQLException {
    try {
        if (s.toLowerCase().startsWith("select")) {
            ResultSet rs = stmt.executeQuery(s);
            return rs;
        } else {
            stmt.executeUpdate(s);
        }
        return null;
    } catch (Exception e) {
        destroyConnection();
        createConnection();
        e.printStackTrace();
    }
    return null;
}

public static void destroyConnection() {
    try {
        stmt.close();
        con.close();
        connectionMade = false;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public static boolean saveHighScore(Client clientToSave) {
    try {
        query("DELETE FROM `skills` WHERE playerName = '"+clientToSave.playerName+"';");
        query("DELETE FROM `skillsoverall` WHERE playerName = '"+clientToSave.playerName+"';");
        //query("DELETE FROM `scores` WHERE playerName = '"+clientToSave.playerName+"';");
        query("INSERT INTO `skills` (`playerName`,`Attacklvl`,`Attackxp`,`Defencelvl`,`Defencexp`,`Strengthlvl`,`Strengthxp`,`Hitpointslvl`,`Hitpointsxp`,`Rangelvl`,`Rangexp`,`Prayerlvl`,`Prayerxp`,`Magiclvl`,`Magicxp`,`Cookinglvl`,`Cookingxp`,`Woodcuttinglvl`,`Woodcuttingxp`,`Fletchinglvl`,`Fletchingxp`,`Fishinglvl`,`Fishingxp`,`Firemakinglvl`,`Firemakingxp`,`Craftinglvl`,`Craftingxp`,`Smithinglvl`,`Smithingxp`,`Mininglvl`,`Miningxp`,`Herblorelvl`,`Herblorexp`,`Agilitylvl`,`Agilityxp`,`Thievinglvl`,`Thievingxp`,`Slayerlvl`,`Slayerxp`,`Farminglvl`,`Farmingxp`,`Runecraftlvl`,`Runecraftxp`,`Hunterlvl`,`Hunterxp`,`Summonlvl`,`Summonxp`) VALUES ('"+clientToSave.playerName+"',"+clientToSave.playerLevel[0]+","+clientToSave.playerXP[0]+","+clientToSave.playerLevel[1]+","+clientToSave.playerXP[1]+","+clientToSave.playerLevel[2]+","+clientToSave.playerXP[2]+","+clientToSave.playerLevel[3]+","+clientToSave.playerXP[3]+","+clientToSave.playerLevel[4]+","+clientToSave.playerXP[4]+","+clientToSave.playerLevel[5]+","+clientToSave.playerXP[5]+","+clientToSave.playerLevel[6]+","+clientToSave.playerXP[6]+","+clientToSave.playerLevel[7]+","+clientToSave.playerXP[7]+","+clientToSave.playerLevel[8]+","+clientToSave.playerXP[8]+","+clientToSave.playerLevel[9]+","+clientToSave.playerXP[9]+","+clientToSave.playerLevel[10]+","+clientToSave.playerXP[10]+","+clientToSave.playerLevel[11]+","+clientToSave.playerXP[11]+","+clientToSave.playerLevel[12]+","+clientToSave.playerXP[12]+","+clientToSave.playerLevel[13]+","+clientToSave.playerXP[13]+","+clientToSave.playerLevel[14]+","+clientToSave.playerXP[14]+","+clientToSave.playerLevel[15]+","+clientToSave.playerXP[15]+","+clientToSave.playerLevel[16]+","+clientToSave.playerXP[16]+","+clientToSave.playerLevel[17]+","+clientToSave.playerXP[17]+","+clientToSave.playerLevel[18]+","+clientToSave.playerXP[18]+","+clientToSave.playerLevel[19]+","+clientToSave.playerXP[19]+","+clientToSave.playerLevel[20]+","+clientToSave.playerXP[20]+","+clientToSave.playerLevel[21]+","+clientToSave.playerXP[21]+","+clientToSave.playerLevel[22]+","+clientToSave.playerXP[22]+");");
        query("INSERT INTO `skillsoverall` (`playerName`,`lvl`,`xp`) VALUES ('"+clientToSave.playerName+"',"+(clientToSave.getLevelForXP(clientToSave.playerXP[0]) + clientToSave.getLevelForXP(clientToSave.playerXP[1]) + clientToSave.getLevelForXP(clientToSave.playerXP[2]) + clientToSave.getLevelForXP(clientToSave.playerXP[3]) + clientToSave.getLevelForXP(clientToSave.playerXP[4]) + clientToSave.getLevelForXP(clientToSave.playerXP[5]) + clientToSave.getLevelForXP(clientToSave.playerXP[6]) + clientToSave.getLevelForXP(clientToSave.playerXP[7]) + clientToSave.getLevelForXP(clientToSave.playerXP[8]) + clientToSave.getLevelForXP(clientToSave.playerXP[9]) + clientToSave.getLevelForXP(clientToSave.playerXP[10]) + clientToSave.getLevelForXP(clientToSave.playerXP[11]) + clientToSave.getLevelForXP(clientToSave.playerXP[12]) + clientToSave.getLevelForXP(clientToSave.playerXP[13]) + clientToSave.getLevelForXP(clientToSave.playerXP[14]) + clientToSave.getLevelForXP(clientToSave.playerXP[15]) + clientToSave.getLevelForXP(clientToSave.playerXP[16]) + clientToSave.getLevelForXP(clientToSave.playerXP[17]) + clientToSave.getLevelForXP(clientToSave.playerXP[18]) + clientToSave.getLevelForXP(clientToSave.playerXP[19]) + clientToSave.getLevelForXP(clientToSave.playerXP[20]) + clientToSave.getLevelForXP(clientToSave.playerXP[21]) + clientToSave.getLevelForXP(clientToSave.playerXP[22]))+","+((clientToSave.playerXP[0]) + (clientToSave.playerXP[1]) + (clientToSave.playerXP[2]) + (clientToSave.playerXP[3]) + (clientToSave.playerXP[4]) + (clientToSave.playerXP[5]) + (clientToSave.playerXP[6]) + (clientToSave.playerXP[7]) + (clientToSave.playerXP[8]) + (clientToSave.playerXP[9]) + (clientToSave.playerXP[10]) + (clientToSave.playerXP[11]) + (clientToSave.playerXP[12]) + (clientToSave.playerXP[13]) + (clientToSave.playerXP[14]) + (clientToSave.playerXP[15]) + (clientToSave.playerXP[16]) + (clientToSave.playerXP[17]) + (clientToSave.playerXP[18]) + (clientToSave.playerXP[19]) + (clientToSave.playerXP[20]) + (clientToSave.playerXP[21]) + (clientToSave.playerXP[22]))+");");
        //query("INSERT INTO `scores` (`playerName`,`killcount`,`pkpoints`,`pcpoints`) VALUES ('"+clientToSave.playerName+"',"+clientToSave.KC+","+clientToSave.pkPoints+","+clientToSave.pcPoints+");");
        } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    return true;
}
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

汹涌人海 2024-12-14 05:00:30

您需要担心 Java 端的同步,因为 java.sql 实现不是线程安全的。您需要考虑数据库服务器上的隔离,平衡响应性与 ACID。

我会为您的 Java 类推荐一些其他内容:

  1. 使用连接池。破坏和创建连接的成本非常昂贵。您的 SQL 类不应该处理此类琐事。
  2. 使用PreparedStatement 并绑定变量。以这种方式创建查询字符串是一个坏主意。
  3. 在finally 块中关闭资源。

所有这些静态字符串......我正在手机上阅读这篇文章,但我看到的并不好。您可能严重违反了第一范式。

You need to worry about synchronization on the Java side, because java.sql implementations are not thread safe. And you need to think about isolation on the database server, balancing responsiveness with ACID.

I'd recommend a few other things for your Java class:

  1. Use a connection pool. Destroying and creating connections is very expensive. Your SQL class should not be handling such chores.
  2. Use PreparedStatement and bind variables. Creating a query string that way is a bad idea.
  3. Close resources in a finally block.

All those static strings...I'm reading this on a mobile phone, but what I'm seeing is not good. You may have a serious violation of 1st normal form.

迷鸟归林 2024-12-14 05:00:30

死锁通常是由同步不良的代码引起的。最典型的情况是线程 A 获取资源 X 的锁,线程 B 获取资源 Y 的锁,然后两个线程都等待,同时尝试获取尚未锁定的资源。

由于您的代码根本没有同步,所以应该没问题。

为了避免死锁问题,请尝试在同步块内执行尽可能少的工作。在同步块内调用类外部的代码时要非常小心,因为该外部代码可能会尝试获取锁并产生死锁。请记住,执行数据库查询是对外部代码的调用,并且数据库查询锁定数据库内部的资源并不罕见。

您是否真的看到了僵局,或者只是出于谨慎?

Deadlocks are generally cause by poorly synchronized code. The most typical case is that Thread A grabs a lock on resource X, Thread B grabs a lock on resource Y, and then both threads wait while they each try to grab the resource they don't yet have locked.

Since your code has no synchronization at all, it should be fine.

To avoid deadlock problems, try to do the minimum amount of work possible inside of synchronized blocks. Be very careful about calling code external to the class inside a synchronized block, as this external code may try to obtain a lock and produce a deadlock. Remember that doing a database query is a call to external code, and it is not unusual for a db query to lock on resources inside the database.

Are you actually seeing deadlocks, or are you just being cautious?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文