2010-08-15 83 views
5

我正在嘗試使用與Atomic變量(java.util.concurrent.atomic包)比較的方法使用同步的Java多線程。java在方法上同步不工作?

下面是類:從運行的是原子

// Interface ICounter.java 
     public interface ICounter { 
      public void increment(); 
      public void decrement(); 
      public int value(); 
     } 

// Class Counter.java 
    public class Counter implements ICounter { 
     private int c = 0; 

     @Override 
     public void increment() { 
      c++; 
     } 

     @Override 
     public void decrement() { 
      c--; 
     } 

     @Override 
     public int value() { 
      return c; 
     } 
    } 

// Class AtomicCounter.java 
    import java.util.concurrent.atomic.AtomicInteger; 

    public class AtomicCounter implements ICounter { 
     private AtomicInteger c = new AtomicInteger(0); 

     @Override 
     public void increment() { 
      c.incrementAndGet(); 
     } 

     @Override 
     public void decrement() { 
      c.decrementAndGet(); 
     } 

     @Override 
     public int value() { 
      return c.get(); 
     } 

     public long getIncrement() { 
      return c.incrementAndGet(); 
     } 
    } 

// Class MainProg.java 
    public class MainProg { 
     public static void main(String args[]) { 
      ICounter counter = new AtomicCounter(); 
        //ICounter counter = new SynchronizedCounter(); 
      Thread thread1 = new Thread(new CountRunner(counter)); 
      Thread thread2 = new Thread(new CountRunner(counter)); 

      thread1.start(); 
      thread2.start(); 
     } 
    } 

    class CountRunner implements Runnable { 
     private ICounter counter; 
     public CountRunner(ICounter counter) { 
      this.counter = counter; 
     } 

     public void run() { 
      while (true) { 
       counter.increment(); 
       System.out.println(Thread.currentThread().getName() + " count=" + counter.value()); 
       System.out.println("-------------------"); 
       try { 
        Thread.sleep(2000L); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 

結果或同步不表明變量整數是線程安全的,例如:

Thread-0 count=1 
------------------- 
Thread-1 count=2 
------------------- 
Thread-0 count=3 
------------------- 
Thread-1 count=4 
------------------- 
Thread-0 count=5 
------------------- 
Thread-1 count=6 
------------------- 
Thread-0 count=7 
------------------- 
Thread-1 count=8 
------------------- 
Thread-0 count=10 
------------------- 
Thread-1 count=10 
------------------- 

從結果來看,最後2行顯示2個線程正在訪問計數器類的整數變量的相同值。 也許我在這裏失去了一些東西?

謝謝!

回答

4

您正在增加一個步驟中的值,然後在另一個步驟中獲取值。雖然這些單獨的步驟中的每一步都可以通過下級AtomicInteger原子化,但是您執行兩個單獨操作的事實會使您在打印語句中看到的值受到線程執行順序的支配。

爲了能夠準確地顯示給定線程更新的值,您需要同時在單個操作中更新並獲取結果值,這是您的getIncrement()方法所執行的操作。可以給你預期結果的代碼如下所示:

int changedValue = counter.getIncrement(); 
System.out.println(Thread.currentThread().getName() + " count=" + changedValue); 
2

你錯過了什麼是你的AtomicCounter類不正常工作,併發生觀察到的行爲becase的線程調用之間切換到.increment().value()

------------------- 
Thread-0 increment -> value = 9 
------------------- 
Thread-1 increment -> value = 10 
------------------- 
Thread-0 print value <- 10 
------------------- 
Thread-1 print value <- 10 
------------------- 
4

因爲你counter.increment()System.out.println是不是一個原子操作。

Thread 1    Thread2 

increment 

         increment 

         System.out.println // print 10 

System.out.println 
// print 10 too