0

我正在学习 K&B 线程章节。我正在阅读有关同步的内容。这是 K&B 的一个例子。

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());
    }
 }
}

K&B 谈到了同步方法和同步块。这是K&B的参考段落。

当一个方法在同步块中执行代码时,代码被称为在同步上下文中执行。同步方法时,调用该方法的对象就是必须获取锁的对象。但是当我们同步代码块时,您必须指定要使用哪个对象的锁作为锁。

那么在这个例子中,会在 AccountDanger 实例或 Account 对象上获取锁吗?我认为应该是AccountDanger。我的看法正确吗?如果是 AccountDanger 对象,并且一个线程获得了 AccountDanger 的锁,那么其他线程是否可以调用非同步方法?

4

2 回答 2

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

所以在这个例子中,第一个调用这个方法的线程会进入synchronizedblock获取this对象monitor并持有它,除了第一个线程本身之外没有其他线程可以再次获取monitor锁this。调用此方法的所有其他线程将阻塞,直到第一个线程释放锁并释放监视器。

注意:用于同步块的锁本质上是可重入的。

于 2013-08-09T10:41:35.383 回答
0

那么在这个例子中,会在 AccountDanger 实例或 Account 对象上获取锁吗?

是的。我经常看到的一个技巧是this在您只有一小段代码实际上需要同步时进行同步。例如:

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

一般来说,这会加快速度。

于 2013-08-07T15:00:42.003 回答