Ответ 1
Нет, вы должны использовать что-то вроде java.util.concurrent.atomic.AtomicInteger
. Посмотрите на его метод getAndIncrement()
.
Я делаю программу в java, которая раскачивает несколько автомобилей друг против друга. Каждый автомобиль - отдельная нить.
Когда автомобили завершают гонку, каждый из них называет этот метод. Я протестировал метод с различными скоростями таймера, и он работает нормально. Но я понимаю, что каждый поток обращается к переменной carsComplete, иногда в то же самое время (по крайней мере, в области, которую дает мне команда date).
Итак, мой вопрос: этот метод небезопасен?
public static String completeRace()
{
Date accessDate = new Date();
System.out.println("Cars Complete: " + carsComplete + " Accessed at " + accessDate.toString());
switch(++carsComplete)
{
case 1: return "1st";
case 2: return "2nd";
case 3: return "3rd";
default: return carsComplete + "th";
}
}
Нет, вы должны использовать что-то вроде java.util.concurrent.atomic.AtomicInteger
. Посмотрите на его метод getAndIncrement()
.
Предварительное увеличение на int
не потокобезопасное, используйте AtomicInteger
, который не блокируется:
AtomicInteger carsComplete = new AtomicInteger();
//...
switch(carsComplete.incrementAndGet())
Кстати, ниже приведен код не потокобезопасный. Можете ли вы объяснить, почему?
carsComplete.incrementAndGet();
switch(carsComplete.get())
++ не является атомарным. Посмотрите здесь http://madbean.com/2003/mb2003-44/.
Для атомных операций вы можете использовать AtomicInteger
AtomicInteger atomicInteger = new java.util.concurrent.atomic.AtomicInteger(0)
и каждый раз, когда вы хотите увеличить, вы можете вызвать метод atomicInteger.incrementAndGet()
, который возвращает примитивный int. 0 - начальное значение по умолчанию для атомного целого.
То же, что и в С++, оператор ++
не является атомарным.
На самом деле выполняется более 1 команды под капотом (не обманывайтесь, видя просто ++i
, это load/add/store
), и поскольку в игре задействовано более 1 команды без синхронизации, вы можете иметь различные перемежения с неправильными результатами.
Если вам нужно добавить carsComplete
в потокобезопасной манере, вы можете использовать конструкцию java AtomicInteger
или вы можете синхронизировать весь метод
Вопрос: "is pre increment operator thread safe?"
Ans: Нет, почему? из-за количества инструкций. Атомные средства - одна операция, здесь должны выполняться операции загрузки/добавления/хранения. Итак, не атомная операция.
Same for post increment.