Является ли оператор предварительного инкремента потокобезопасным?

Я делаю программу в 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";    
      }
 }

Ответ 1

Нет, вы должны использовать что-то вроде java.util.concurrent.atomic.AtomicInteger. Посмотрите на его метод getAndIncrement().

Ответ 2

Предварительное увеличение на int не потокобезопасное, используйте AtomicInteger, который не блокируется:

AtomicInteger carsComplete = new AtomicInteger();

//...

switch(carsComplete.incrementAndGet())

Кстати, ниже приведен код не потокобезопасный. Можете ли вы объяснить, почему?

carsComplete.incrementAndGet();
switch(carsComplete.get())

Ответ 3

Оператор

++ не является атомарным. Посмотрите здесь http://madbean.com/2003/mb2003-44/. Для атомных операций вы можете использовать AtomicInteger

AtomicInteger atomicInteger = new java.util.concurrent.atomic.AtomicInteger(0)

и каждый раз, когда вы хотите увеличить, вы можете вызвать метод atomicInteger.incrementAndGet(), который возвращает примитивный int. 0 - начальное значение по умолчанию для атомного целого.

Ответ 4

То же, что и в С++, оператор ++ не является атомарным.

На самом деле выполняется более 1 команды под капотом (не обманывайтесь, видя просто ++i, это load/add/store), и поскольку в игре задействовано более 1 команды без синхронизации, вы можете иметь различные перемежения с неправильными результатами.

Если вам нужно добавить carsComplete в потокобезопасной манере, вы можете использовать конструкцию java AtomicInteger или вы можете синхронизировать весь метод

Ответ 5

Вопрос: "is pre increment operator thread safe?"

Ans: Нет, почему? из-за количества инструкций.     Атомные средства - одна операция, здесь должны выполняться операции загрузки/добавления/хранения. Итак, не атомная операция.

  Same for post increment.