2016-08-29 139 views
1

我是新來的java和嘗試與示例程序同步使用multiThreading添加數字到100。以下是我能夠提出的代碼。當我測試代碼時,它有時會給出正確的值4590,但有時不會給出正確的值。任何人都可以指出我在做什麼錯Java同步問題

class Counter{ 
    Integer counter = 0; 

    public void increment(int i){ 
     synchronized (counter){ 
      counter += i; 
     } 
    } 
} 

class ObjectTest implements Runnable{ 

    int i; 
    Counter blah; 

    public ObjectTest(Counter counter,int i){ 
     blah =counter; 
     this.i = i; 
    } 
    @Override 
    public void run() { 
     blah.increment(i); 
    } 
} 

public class SyncTest { 

    public static void main(String args[]) throws InterruptedException { 
     ThreadPoolExecutor executor = new ThreadPoolExecutor(4,10,60, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.CallerRunsPolicy()); 
     Counter counter = new Counter(); 
     for (int index = 0; index < 100; index++) { 
      ObjectTest objectTest = new ObjectTest(counter,index); 
      executor.execute(objectTest); 
     } 
     executor.shutdown(); 
     while (!executor.isTerminated()){ 
      Thread.sleep(1000L); 
     } 

     System.out.println(counter.counter); 
    } 
} 

回答

2

,因爲它是一個Integer,這是不可改變的,您不能在counter同步。因此counter += i會創建一個新的Integer對象,該對象與已同步的對象不同。

您可以製作它int counter並有一個單獨的Object lock = new Object();,同步lock

+2

您可以在整數(或任何對象)上同步,而不是您正在遞增的那個... – RealSkeptic

+0

是的,我的聲明適用於此特定代碼。你可以在你正在增加的Integer上進行同步,但它不會導致運行良好的代碼。 – Kayaman

+0

你顯然理解這個問題,但是你的答案與新手想法不太一致。新手不能完全掌握對象,變量和表達式之間的差異。你說「因爲Integer是不可變的,但是你真正的意思是」,因爲'Integer'對象是不可變的,'counter'變量必須是_mutable_。這是計數器變量的可變性導致的問題,而不是Integer對象的不可變性。 –