0

以下のコードがスレッドセーフではない理由を教えてください。取得する出力は、0 または 45 または 90 のいずれかです。共有リソース カウンターには同期メソッドがあるため、常に出力として 90 を期待しています。ここで何か不足していますか?お知らせ下さい。このコードをスレッドセーフにする方法も教えてください。

class Counter{

    long count = 0;

    public synchronized void add(long value){
      this.count += value;
    }
 }
 class CounterThread extends Thread{

    protected Counter counter = null;

    public CounterThread(Counter counter){
       this.counter = counter;
    }

    public void run() {
    for(int i=0; i<10; i++){
          counter.add(i);
       }
    }
 }
 public class Example {

   public static void main(String[] args){

     Counter counter = new Counter();
     Thread  threadA = new CounterThread(counter);
     Thread  threadB = new CounterThread(counter);

     threadA.start();
     threadB.start();

     System.out.println(counter.count);
   }
 }
4

6 に答える 6

11

スレッドが終了するのを待ちます。追加

threadA.join();
threadB.join();

結果を印刷する前に。

于 2012-08-28T07:02:40.380 に答える
6

基本的に、2 つのスレッドが実行を完了する前に値を読み取っています。

結合を使用して、スレッドが終了するまで待機できます。

また、同期された add メソッドの代わりにAtomicLongのメソッドを使用してみてください。addAndGet

于 2012-08-28T06:59:01.610 に答える
3

スレッドが停止するまで、println で待機しません。そのため、for ループがまだ処理中にカウンターの値を出力します。スレッドセーフで何もする必要はありません。

于 2012-08-28T06:49:38.307 に答える
2

Counterアクセスはスレッドセーフですが、System.out.println(counter.count);他のスレッドが作業を行う前に発生する可能性があります。

于 2012-08-28T06:51:57.867 に答える
1

コードはスレッドセーフですが、より良い方法は、同期されたメソッドを取り除き、AtomicLong を使用してgetAndAdd(long)メソッドを使用することです。

public final long getAndAdd(long delta)
>Atomically add the given value to current value. 
于 2012-08-28T06:58:05.020 に答える
0

そこでは 3 つのスレッドが実行されています。variableに割り当てられたもの、およびメインスレッドthreadAに割り当てられたもの。threadB

mainメソッドが実行されている限り、メイン スレッドは実行されます。他の 2 つは開始され、メイン スレッドと同時に実行されます。ただし、メイン スレッドは他の 2 つのスレッドが終了するのを待ってブロックされないため、実行の機会が得られたときに結果を出力します。

于 2012-08-28T06:54:15.800 に答える