Я пишу код всплеска, который не дает мне результатов, которые я ожидаю.java.sql.Connection Уровень изоляции
У меня есть таблица, которая в основном представляет собой строки счетчиков. Другие таблицы используют эти строки для генерации уникальных идентификаторов. Когда я запускаю код ниже того, что я исключал, это то, что первый поток, который достигнет оператора select, получит блокировку в этой строке или таблице, останавливая все чтение или запись по уникальному значению id. Однако второй поток всегда завершается до первого, из-за того, что он был усыпан в течение 1 секунды, поэтому они оба читают одно и то же значение и записывают одно и то же значение, поэтому он только увеличивается один раз и не дважды, как я исключал.
Есть ли что-то не так с моим кодом, или мое понимание уровня изоляции неверно?
Я снял код плиты котла. Стандартное sql.Connection с использованием базы данных MySQL.
private void incrementValue() {
connection
.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
statement = connection.createStatement();
System.out.println(Thread.currentThread().getName()
+ " doing select");
resultSet = statement.executeQuery("select * from counter");
System.out.println(Thread.currentThread().getName()
+ "after select");
if (counter++ == 0) {
Thread.sleep(1000);
}
String incrementedValue = getIncrementedValue(resultSet);
statement.executeUpdate("update counter set counter='"
+ incrementedValue + "'");
}
private String getIncrementedValue(ResultSet resultSet) throws SQLException {
String value = "";
if (resultSet.next()) {
System.out.println(Thread.currentThread().getName() + "Value was "
+ resultSet.getString(1));
value = (new Integer(resultSet.getString(1)) + 1) + "";
}
return value;
}
Это называется от главного
public static void main(String[] args) {
DatabaseExample databaseExample = new DatabaseExample();
Runnable runnable = new Runnable() {
@Override
public void run() {
DatabaseExample databaseExample = new DatabaseExample();
databaseExample.incrementValue();
}
};
new Thread(runnable).start();
databaseExample.incrementValue();
}
В этом случае замок должен быть выполнен с применением уровня. Просто синхронизируйте свой метод, используя ключевое слово 'synchronized'. Обратите внимание, что это повлияет на производительность приложения. –