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

本质上,您是在两个线程完成执行之前读取值。

您可以使用连接来等待线程完成。

也尝试使用AtomicLongaddAndGet方法而不是同步的 add 方法。

于 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个线程在那里运行。分配给变量threadA的一个,分配给threadB主线程的一个。

只要main方法运行,主线程就会运行。其他 2 个启动并与主线程同时运行。但是,主线程不会阻塞等待其他 2 个完成,因此它会在有机会执行时打印结果。

于 2012-08-28T06:54:15.800 回答