同步方法不是线程安全的

时间:2012-08-28 06:42:01

标签: java multithreading synchronization

有人可以告诉我为什么以下代码不是线程安全的?我得到的输出是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);
   }
 }

6 个答案:

答案 0 :(得分:12)

等待线程完成。添加

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

在打印结果之前。

答案 1 :(得分:6)

实际上,在两个线程完成执行之前,您正在读取值。

您可以使用join等待线程完成。

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

答案 2 :(得分:3)

在线程停止之前,您不必等待println。因此,当for循环仍在进行时,您打印出计数器的值。它不需要对线程安全做任何事情。

答案 3 :(得分:2)

Counter访问是线程安全的,但System.out.println(counter.count);可以在其他线程完成其工作之前发生。

答案 4 :(得分:1)

您的代码是线程安全的,但更好的方法是摆脱同步方法并使用AtomicLong 并使用getAndAdd(long)方法

public final long getAndAdd(long delta)
>Atomically add the given value to current value. 

答案 5 :(得分:0)

你有3个线程在那里运行。分配给变量threadA的分配给threadB和主线程的分配。

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