2012-12-05 127 views
4

带同步的简单多线程测试。我想如果它是“同步的”,其他线程会等待。我错过了什么?使用同步的Java多线程不是线程安全的

public class MultithreadingCounter implements Runnable { 

    static int count = 0; 

    public static void main(String[] args) { 
     int numThreads = 4; 
     Thread[] threads = new Thread[numThreads]; 

     for (int i = 0; i < numThreads; i++) 
      threads[i] = new Thread(new MultithreadingCounter(), i + ""); 

     for (int i = 0; i < numThreads; i++) 
      threads[i].start(); 

     for (int i = 0; i < numThreads; i++) 
      try { 
       threads[i].join(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
    }   

    @Override 
    public void run() { 
     increment(); 
    } 

    public synchronized void increment(){ 
      System.out.print(Thread.currentThread().getName() + ": " + count + "\t"); 
      count++; // if I put this first or increment it directly in the print line, it works fine. 
    } 
} 

我认为这将显示类似:

0: 1 2: 0 1: 2 3: 3  

但其实际输出:

0: 0 2: 0 1: 0 3: 3  

和其他变化是这样的。它应该显示每个增量(即0,1,2,3)不按顺序...

回答

7

您的​​关键字位于实例方法上。没有两个线程可以同时执行您的线程对象之一的此方法。但是,这不是你的代码所做的。每个线程在自己的实例上执行该方法。同步不会做你想要的。如果它是一个static方法,它会。

+0

啊。我每天都会学到新的东西。谢谢。 – user1877411

+0

会使它成为'static'(与'synchronized'结合)充分地关闭它,还是应该使变量volatile? –

+1

(正确)同步就足够了。它已确保增量与后续读取之间具有发生之前的关系,这是“易失性”会增加的所有内容。 –

1

increment方法应该是static

public static synchronized void increment() { 

现在,每个对象在个别情况下同步,但由于count是一个静态变量,你应该Class对象本身上同步。

+1

我是让你得到3000代表的人,耶:D – Doorknob

0

当在方法之前使用synchronized关键字时,它确保该方法只能针对该对象一次仅由一个线程执行。它不能确保其他对象的线程安全。