2013-08-07 42 views
0

我正在學習K & B線程章節。我正在閱讀關於同步。下面是從 ķ& B.Synchronizaton Object Lock Confusion

public class AccountDanger implements Runnable { 
    private Account account = new Account(); 
    public void run() { 
    for(int x =0 ; x < 5 ; x++){ 
     makeWithdrawl(10); 
     if(account.getBalance() < 0){ 
     System.out.println("account is overdrawn"); 
     } 
    } 
    } 
    public static void main(String[] args){ 
    AccountDanger accountDanger = new AccountDanger(); 
    Thread one = new Thread(accountDanger); 
    Thread two = new Thread(accountDanger); 
    one.setName("Fred"); 
    two.setName("Lucy"); 
    one.start(); 
    two.start(); 
    } 

    private synchronized void makeWithdrawl(int amt){ 
    if(account.getBalance() >= amt){ 
     System.out.println(Thread.currentThread().getName() + " is going to withdraw"); 

    try{ 
     Thread.sleep(500); 
    } 
    catch(InterruptedException e) { 
     e.printStackTrace(); 
    } 
    account.withdraw(amt); 
    System.out.println(Thread.currentThread().getName() + " completes the withdrawl"); 
    } 
    else{ 
     System.out.println("Not enough in account for " + Thread.currentThread().getName() + " to withdraw " + 
     account.getBalance()); 
    } 
} 
} 

ķ&約同步方法和同步塊B的會談的例子。這裏選自K & B.

當方法是從同步塊內執行的代碼段引用,代碼 據說以同步的上下文中執行。當您同步一個方法時,用於調用該方法的對象是必須獲取其鎖定的對象 。但是,當我們同步代碼塊 時,您必須指定要將哪個對象的鎖用作鎖。

所以在這個例子中,將在AccountDanger實例或Account對象上獲取鎖嗎? 我認爲應該是AccountDanger。我覺得正確嗎?如果它是AccountDanger對象, 和一個線程獲得了AccountDanger的鎖定,那麼其他線程是否可以調用非同步方法?

+2

是的,它在AccountDanger對象上(隱式地,因爲該方法具有synchronized關鍵字)。 – Kayaman

+0

謝謝卡亞曼。那麼這是否意味着一個線程獲取了當前對象的鎖定,其他線程無法訪問任何其他非同步方法? – benz

+0

否。這意味着其他線程無法訪問其他同步方法。非同步方法可以被訪問,因爲它們沒有被對象監視器保護。 – Kayaman

回答

0

那麼在這個例子中,將鎖定AccountDanger 實例或Account對象嗎?

是的。我見過的一個技巧就是在this上同步,當你只有一小塊代碼需要同步時。例如:

int balance = -1; 
synchronized(this) { 
    balance = account.getBalance(); 
    account.withdraw(amt); 
} 
//IO, etc. after that. 

一般來說,這會加快速度。

0
private synchronized void makeWithdrawl(int amt){ 
    //is implicitly acquiring lock on this object (AccountDanger object)    
} 

所以本例中的第一線程調用此方法將進入​​塊獲取this對象監視器並將其保持和除所述第一線程本身可以在this再次獲取監視器鎖沒有其他線程。調用此方法的所有其他線程都將阻塞,直到第一個線程釋放鎖定並釋放監視器。

注意:用於同步塊的鎖本質上是Re-entrant