2016-01-26 130 views
0

我目前正在學習Java中的同步。據我瞭解,一個同步實例方法獲取對象的鎖。Java多線程共享同一對象的同步問題

我的程序是一個50個任務,然後每個給定一個線程。每個任務都將一分錢添加到由Account類創建的Account對象。

賬戶類有一個餘額數據字段和一個同步存款方法。 50個任務具有指向相同賬戶對象(即共享賬戶)的賬戶字段。一旦運行被調用,每個任務將調用account.deposit實例方法來存入1個單元。

我希望餘額以50個單位結尾。令人驚訝的是,賬戶最終有50個有時或其他餘額14,48,33等。

class JavaStudy { 
    public static void main(String[] args){ 

     for (int j = 0; j < 10; j++) { 

      Account account = new Account(); 

      ExecutorService executorPool = Executors.newFixedThreadPool(50); 

      for (int i = 0; i < 50; i++) { 
       executorPool.execute(new DepositTask(account)); 
      } 

      executorPool.shutdown(); 

      while(!executorPool.isShutdown()){ 
      } 

      System.out.println(account.getBalance()); 
     } 
    } 
} 

存款任務類!

class DepositTask implements Runnable { 

    private Account account; 

    DepositTask(Account account){ 
     this.account = account; 
    } 

    @Override 
    public void run() { 
     account.deposit(1); 
    } 
} 

賬戶類別!根據我所理解的,據我所知,當任務訪問account.deposit(1)時,帳戶應該被鎖定;然後, 。其他任務應該無法訪問它,因爲它們共享相同的對象!不知何故,這是不會的,我結束了下面的結果,

Balance: 20 
Balance: 47 
Balance: 50 
Balance: 42 
Balance: 27 
Balance: 24 
Balance: 50 
Balance: 29 
Balance: 13 
Balance: 12 

Process finished with exit code 0 

對發生了什麼事情的任何想法?

+1

簡化這個 「而{}(executorPool.isShutdown()!)」 - 有阻塞的方法來實現等待終止!請不要這樣做! – Fildor

回答

5

我懷疑你不是在等待與關機不同的終止。這可能意味着並非所有任務都已完成。

executorPool.shutdown(); 
executorPool.awaitTermination(1, TimeUnit.MINUTES); 
System.out.println(account.getBalance()); 

BTW在Java 8,你可以用

Account account = new Account(); 

InStream.range(0, 50).parallel() 
        .forEach(i -> account.deposit(1)); 

System.out.println(account.getBalance()); 
+0

@OldCurmudgeon感謝您的更正。 –

+1

謝謝!這解決了問題!關機可防止執行器池接受進一步的任務,但正在處理的任務仍在運行!那就是爲什麼,就像你說的那樣,這個平衡顯示出了不連貫的價值! –