尝试可视化和理解同步。
代码A
public class MyClass1 {
private static final Object lock = new Object();
public MyClass1() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
代码B
public class MyClass2 {
private final Object lock = new Object();
public MyClass2() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}
注意
上面的代码显示了构造函数,但您可以在静态方法和非静态方法中讨论行为的不同之处。另外,当synchronized块修改静态成员变量时使用静态锁是否有利?
我已经在this question查看了答案,但不清楚不同的使用方案是什么。
答案 0 :(得分:46)
区别很简单:如果锁定对象位于static
字段中,则MyClass*
的所有实例将共享该锁定(即没有两个对象将能够同时锁定该对象。)
如果该字段是非静态的,则每个实例都有自己的锁,因此只有对同一对象上的方法的调用才会相互锁定。
使用静态锁定对象时:
o1.foo()
o1.foo()
,必须等待线程1完成o2.foo()
,还必须等待线程1(可能还有2)完成使用非静态锁定对象时:
o1.foo()
o1.foo()
,必须等待线程1完成o2.foo()
,它可以继续,而不是注意线程1和2 您需要哪一项取决于您尝试使用同步块保护的数据类型。
根据经验,您希望锁定对象具有与操作值相同的static
- ness。因此,如果您仅操作非静态值 ,则需要非静态锁定对象。如果您只操作静态值 ,则需要一个静态锁定对象。
当你操纵静态和非静态值时,它会变得复杂。 easy 方式只是使用静态锁定对象,但这可能会增加synchronized块的大小,而不是绝对必要,并且可能需要比预期更多的锁争用。在这些情况下,您可能需要静态和非静态锁定对象的组合。
在您的特定情况下,您在构造函数中使用了锁,每个实例只执行一次,因此非静态锁对象在这里没有任何意义。