清单 4. 等效的代码
synchronized void f() {
void f() {
// 执行某些操作
synchronized(this) {
}
// 执行某些操作
}
}
所以,为了确保 addMember() 和 addAlt() 方法不彼此阻塞,可按清单 5 所示重写 Jury 类。
清单 5. 重写后的 Jury 类
import java.util.*;
public class Jury {
Vector members;
Vector alternates;
public Jury() {
members = new Vector(12, 1);
alternates = new Vector(12, 1);
}
public void addMember(String name) {
synchronized(members) {
members.add(name);
}
}
public void addAlt(String name) {
synchronized(alternates) {
alternates.add(name);
}
}
public Vector all() {
Vector retval;
synchronized(members) {
retval = new Vector(members);
}
synchronized(alternates) {
retval.addAll(alternates);
}
return retval;
}
}
请注意,我们还必须修改 all() 方法,因为对 Jury 对象同步已没有意义。在改写后的版本中,addMember()、addAlt() 和 all() 方法只访问与 members 和 alternates 对象相关的锁,因此锁定 Jury 对象毫无用处。另请注意,all() 方法本来可以写为清单 6 所示的形式。
清单 6. 将 members 和 alternates 用作同步的对象
public Vector all() {
synchronized(members) {
synchronized(alternates) {
Vector retval;
retval = new Vector(members);
retval.addAll(alternates);
}
}
return retval;
}
但是,因为我们早在需要之前就获得 members 和 alternates 的锁,所以这效率不高。清单 5 中的改写形式是一个较好的示例,因为它只在最短的时间内持有锁,并且每次只获得一个锁。这样就完全避免了当以后增加代码时可能产生的潜在死锁问题。