主要利用到了MySQL中select + for update操作来达到互斥的效果。
public static <T> T lockWithMutex(String lockName, DataSource dataSource, Callable<T> runnable) throws Exception {
Connection connection = null;
boolean autoCommit = false;
PreparedStatement stmt = null;
long start = System.currentTimeMillis();
T result;
try {
connection = dataSource.getConnection();
autoCommit = connection.getAutoCommit();
connection.setAutoCommit(false);
stmt = connection.prepareStatement("SELECT lock_name FROM lock WHERE lock_name = '" + lockName + "' FOR UPDATE");
stmt.execute();
result = runnable.call();
} catch (Exception exception) {
log.error("operation with mutex fail", exception);
throw exception;
} finally {
releaseMutex(stmt, connection, autoCommit);
}
return result;
}
private static void releaseMutex(PreparedStatement stmt, Connection connection, boolean autoCommit) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.error("error occurred while closing prepared statement", e);
}
}
if (connection != null) {
try {
connection.commit();
} catch (SQLException e) {
log.error("error occurred while committing transaction", e);
}
try {
connection.setAutoCommit(autoCommit);
} catch (SQLException e) {
log.error("error occurred while setting auto commit property of connection", e);
}
try {
connection.close();
} catch (SQLException e) {
log.error("error occurred while closing connection", e);
}
}
}