我正在学习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&amp; B谈论同步方法和同步块。以下是K&amp; B的段落。
当一个方法从synchronized块内执行代码时,代码 据说是在同步的上下文中执行。当你 同步一个方法,用于调用方法的对象是 必须获取其锁的对象。但是当我们同步块时 代码,您必须指定要用作锁的对象锁。
因此,在此示例中,是否会在AccountDanger实例或Account对象上获取锁定? 我认为应该是AccountDanger。我觉得正确吗?如果是AccountDanger对象, 并且一个线程获得了AccountDanger的锁定,任何其他线程是否能够调用非同步方法?
答案 0 :(得分:0)
因此,在此示例中,将在AccountDanger上获取锁定 实例或帐户对象?
是。我见过的一个技巧是在this
上只有一小段实际需要同步的代码时进行同步。例如:
int balance = -1;
synchronized(this) {
balance = account.getBalance();
account.withdraw(amt);
}
//IO, etc. after that.
总的来说,这会加快速度。
答案 1 :(得分:0)
private synchronized void makeWithdrawl(int amt){
//is implicitly acquiring lock on this object (AccountDanger object)
}
因此在示例中,调用此方法的第一个线程将进入synchronized
块获取this
对象监视器并保留它,除了第一个线程本身之外没有其他线程可以再次获取监视器锁定this
。调用此方法的所有其他线程将阻塞,直到第一个线程释放锁并释放监视器。
注意:用于同步块的锁本质上是Re-entrant。