Я пишу приложение Java, которое запускает асинхронные потоки для чтения и обновления значений из одной базы данных. Каждый поток получает соединение из пула соединений (c3p0). Я должен предотвратить условия гонки, потому что мне нужно обновлять записи на основе их текущих значений. Поэтому чтение данных с помощью оператора SELECT
, а затем его обновление с помощью инструкции UPDATE
вызовет условие гонки, и поэтому оно не будет потокобезопасным. Я уже нашел некоторые решения, как предотвратить такие условия гонки, но у меня все еще есть некоторые вопросы.Java MySQL предотвращает состояние гонки
Например, я могу использовать вид UPDATE ExampleTable SET ExampleValue = ExampleValue + '5' WHERE Id = '10'
для увеличения значений потокобезопасности. Я читал, что это атомное утверждение. Поэтому мой первый вопрос: Выполняет ли PreparedStatement
в java всегда потокобезопасный? Я так думаю, потому что (если autoCommit верно), каждый отдельный исполняемый оператор является транзакцией, а транзакции являются атомарными, верно? Если да, это также случай, если я вызываю процедуру с выражением или если я помещаю несколько запросов в один оператор, разделенный точкой с запятой?
Я также прочитал, что я могу установить autoCommit в false и выполнить несколько операторов перед выполнением, что также обеспечивает безопасность потоков, поскольку никакая другая инструкция не может прервать транзакцию. Это правильно?
Есть ли какие-либо дополнительные решения для предотвращения таких условий гонки?
Я думаю, что [это] (http://stackoverflow.com/a/2713427/898478) отвечает на некоторые из ваших вопросов, вы его проверяли? Специально: * «Дайте каждой теме свое собственное соединение» *. Я делаю это через пул соединений, и у меня нет условий гонки (хотя я использую PostgreSQL, а не MySQL). – m0skit0
Я использую Пул соединений, и каждый поток имеет свой собственный объект Connection из пула. Но условия гонки все еще возможны при использовании отдельных инструкций для чтения и письма. – stonar96
Как отвечает EJP, используйте 'SELECT FOR UPDATE', таким образом вы имеете только одно утверждение. Если вы хотите выполнить больше запросов/обновлений или 'SELECT FOR UPDATE', это не вариант, вам необходимо обернуть их в транзакцию (конечно же, одно соединение на поток). – m0skit0