2016-09-05 83 views
-3

以下代码同步块与在Java中

public class Coordination { 

    private volatile int counter = 0; 

    public static void main(String ... args) throws Exception { 
     new Coordination().volatileWithCoordination(); 
    } 

    public synchronized void inc() { 
     counter++; 
    } 

    public void volatileWithCoordination() throws Exception { 

     Thread th1 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       for(int k = 0; k < 10_000_000; k++) { 
        synchronized(this) { 
         //inc(); 
         counter++; 
        } 
       } 
      }}); 

     Thread th2 = new Thread(new Runnable() { 

      @Override 
      public void run() { 
       for(int k = 0; k < 10_000_000; k++) { 
        //synchronized(this) { 
        inc(); 
        //counter++; 
        //} 
       } 

      }}); 

     th1.start(); 
     th2.start(); 

     th1.join(); 
     th2.join(); 
     System.out.println("counter: "+counter); 
    } 
} 
counter: 18025867

展品不正确的,非确定性的结果而切换到同步方法限定符:在可运行的第一个线程的

  inc(); 
     //counter++; 

th1)给出的预期输出:

counter: 20000000 

什么造成这种lost update行为,为什么在这种情况下同步方法的行为与同步(this)块不同?

预先感谢您。

+3

块在两个独立线程实例上同步,但该方法在同一个坐标实例上同步。 –

回答

1

两个线程需要获得相同物体上的监视器,以下变化(在任一2个线程或两者的)固定的情况:

synchronized(Coordination.this) { 
        inc(); 
       //counter++; 
       } 
1

你的线程同步于不同的对象。您的​​线程调用同步的inc()方法,该方法在Coordination类的实例上同步;但是当您的th1线程确实是synchronized(this)时,this关键字指的是匿名内部Runnable类的实例,而不是Coordination类。