2010-08-15 66 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