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

时间:2011-10-03 20:55:27

标签: 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";    
      }
 }

5 个答案:

答案 0 :(得分:26)

不,你应该使用像java.util.concurrent.atomic.AtomicInteger这样的东西。看看它的getAndIncrement()方法。

答案 1 :(得分:9)

int上的预增量线程安全,请使用无锁的AtomicInteger

AtomicInteger carsComplete = new AtomicInteger();

//...

switch(carsComplete.incrementAndGet())

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

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

答案 2 :(得分:7)

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

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

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

答案 3 :(得分:6)

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

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

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

答案 4 :(得分:2)

问题是“预增量运算符线程是否安全?”

答:不,为什么?因为涉及的指令数量。       原子意味着单一操作,这里需要执行加载/添加/存储操作。所以不是原子操作。

  Same for post increment.
相关问题