2015-08-28 99 views
0

takeAmount和addAmount僅僅是從balanceAccount添加/子值(例如,添加11,12 ...,20或添加101,102 ...,110)。 balanceAccount有兩個版本,一個是使用synchronized函數,另一個是使用synchronized塊。Java同步函數工作,同步塊不工作

BalanceAccount_synchronizedBlock和BalanceAccount_synchronizedFunction之間有什麼不同嗎?

確實BalanceAccount_synchronizedFunction始終返回0,而BalanceAccount_synchronizedBlock不會。

And ...爲什麼它會顯示不同的行爲?

public class mainStart { 
    public static void main(String args[]) 
    { 
     for (int i=1;i<3000;i=i+10) 
     { 
      new Thread(new addAmount(i)).start(); 
      new Thread(new takeAmount(i)).start(); 
     } 

     try { 
      Thread.sleep(10000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     //BalanceAccount_synchronizedBlock.printAmount(); 
     BalanceAccount_synchronizedFunction.printAmount(); 
    } 


} 

class takeAmount implements Runnable { 
    private int startFrom; 

    public takeAmount(int start) 
    { 
     this.startFrom=start; 
    } 

    public void run() 
    { 
     for (int i=startFrom;i<startFrom+10;i++) 
      //BalanceAccount_synchronizedBlock.sub(i); 
      BalanceAccount_synchronizedFunction.sub(i); 
    } 

} 

class addAmount implements Runnable { 
    private int startFrom; 

    public addAmount(int start) 
    { 
     this.startFrom=start; 
    } 

    public void run() 
    { 
     for (int i=startFrom;i<startFrom+10;i++) 
      //BalanceAccount_synchronizedBlock.add(i); 
      BalanceAccount_synchronizedFunction.add(i); 
    } 

} 

public class BalanceAccount_synchronizedBlock { 
    public static Integer amount=0; 

    public static void add(int a) 
    { 
     synchronized (amount) 
     { 
      amount = amount + a; 
     } 
    } 

    public static void sub(int a) 
    { 
     synchronized (amount) 
     { 
      amount = amount - a; 
     } 
    } 

    public synchronized static void printAmount() 
    { 
     System.out.println("Amount " + amount); 
    } 

} 

public class BalanceAccount_synchronizedFunction { 
    public static Integer amount=0; 

    public synchronized static void add(int a) 
    { 
      amount = amount + a; 
    } 

    public synchronized static void sub(int a) 
    { 
      amount = amount - a; 
    } 

    public synchronized static void printAmount() 
    { 
     System.out.println("Amount " + amount); 
    } 

} 
+0

它顯示了什麼不同的行爲? – RealSkeptic

+3

不要在'Integer'上同步,因爲它是不可變的,當'amount'被替換時,你會在不同的對象上同步,這會導致有趣的問題。你可以使用'Object lock = new Object();'來代替同步。 – Kayaman

+0

感謝您的回覆。這行得通。 – user2602196

回答

0

你的印刷方法被定義爲

public synchronized static void printAmount() 

其類本身同步。在嘗試「塊」的情況下,這些塊在amount上同步,而打印方法正在同步該類。更改該方法以使用在amount上同步的塊。

由於Kayaman指出,你也有問題,你正在同步一個變量(amount)其對象在不斷變化。相反,聲明僅用於同步的private static final Object LOCK = new Object() - 或者更好,只需使用AtomicInteger即可。

+0

感謝您的回覆,我嘗試了您的建議併發揮作用。 – user2602196

2

同步方法使用封閉類作爲同步令牌。當您編寫synchronized(amount)時,您正在使用Integer實例作爲同步令牌。由於在這兩種情況下都沒有使用相同的標記,所以鎖定不會按預期發生。

另請注意,Integer是不可變的,並且每次您將值重新分配到amount時,都會創建一個新實例並失去您對上一個值可能具有的任何鎖定。

0

您可以鎖定使用它是通過使用

synchronized (this) { // this is similar to method level synchronization 

或使用其他然後量整數另一個類級別對象調用此方法的對象(如@Kayaman指出,這是不可改變的所以每次新整數對象在您更新時創建)

public class BalanceAccount_synchronizedBlock { 
    public static Integer amount=0; 
    public static Object Lock = new Object(); 

    public static void add(int a) { 
     synchronized (Lock) { 
      amount = amount + a; 
     } 
    }