预增量运算符是否是线程安全的?

Tra*_*xel 19 java multithreading pre-increment

我正在用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";    
      }
 }
Run Code Online (Sandbox Code Playgroud)

duf*_*ymo 27

不,你应该使用类似的东西java.util.concurrent.atomic.AtomicInteger.看看它的getAndIncrement()方法.

  • 或者在递增之前同步某事. (4认同)

Tom*_*icz 9

在预增int不是线程安全的,使用的AtomicInteger是无锁:

AtomicInteger carsComplete = new AtomicInteger();

//...

switch(carsComplete.incrementAndGet())
Run Code Online (Sandbox Code Playgroud)

顺便说一句,下面的代码也不是线程安全的.你能说出原因吗?

carsComplete.incrementAndGet();
switch(carsComplete.get())
Run Code Online (Sandbox Code Playgroud)


Nar*_*ala 7

++运算符不是原子的.请看http://madbean.com/2003/mb2003-44/.对于原子操作,您可以使用AtomicInteger

AtomicInteger atomicInteger = new java.util.concurrent.atomic.AtomicInteger(0)
Run Code Online (Sandbox Code Playgroud)

每次想要增加时,都可以调用atomicInteger.incrementAndGet()返回原始int的方法.0是原子整数的默认初始值.

  • @Hardik没有竞争条件因为`之前发生'(http://en.wikipedia.org/wiki/Happened-before)关系是由原子操作强制执行的,因此导致线程安全. (2认同)

Cra*_*lus 6

与C++相同,运算符++不是原子的.

它实际上是超过1条指令在引擎盖下执行(不要被看到只是一个简单的愚弄++i;它是load/add/store)并且因为没有同步涉及多于1条指令,你可能会有各种错误结果的交错.

如果需要以carsComplete线程安全的方式增加,可以使用java的构造AtomicInteger,也可以同步整个方法