20

私は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";    
      }
 }
4

5 に答える 5

28

いいえ、次のようなものを使用する必要がありますjava.util.concurrent.atomic.AtomicInteger。そのgetAndIncrement()方法を見てください。

于 2011-10-03T20:58:32.563 に答える
9

++ 演算子はアトミックではありません。ここを見てください http://madbean.com/2003/mb2003-44/ . アトミック操作の場合、使用できますAtomicInteger

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

インクリメントするたびatomicInteger.incrementAndGet()に、プリミティブ int を返すメソッドを呼び出すことができます。0 は原子整数のデフォルトの初期値です。

于 2011-10-03T20:59:42.020 に答える
9

事前インクリメント onintはスレッドセーフではありませんAtomicInteger。ロックフリーのものを使用してください:

AtomicInteger carsComplete = new AtomicInteger();

//...

switch(carsComplete.incrementAndGet())

ところで、以下のコードもスレッドセーフではありません。理由がわかりますか?

carsComplete.incrementAndGet();
switch(carsComplete.get())
于 2011-10-03T20:59:56.700 に答える
6

C++ と同じように、演算子++はアトミックではありません。

実際には、内部で複数の命令が実行されています (単純な を見ただけでだまされないでください++i。それは ですload/add/store)。同期せずに複数の命令が関与しているため、さまざまなインターリーブが誤った結果になる可能性があります。

スレッドセーフな方法でincrent する必要がある場合はcarsComplete、Java のコンストラクトを使用するAtomicIntegerか、メソッド全体を同期することができます

于 2011-10-03T21:04:59.350 に答える