我一直在读关于使用静态对象作为锁的文章,最常见的例子是这样的:
public class MyClass1 {
private static final Object lock = new Object();
public MyClass1() {
//unsync
synchronized(lock) {
//sync
}
//unsync
}
}我的问题是,锁定一定要是最终的吗?我知道把它作为final来保证没有人会篡改它的值是很好的,但是没有final它能工作吗?
发布于 2018-03-05 15:49:25
如果不将变量设置为final,并且在与加载NullPointerException的线程不同的线程中创建MyClass1的实例,则可能会在MyClass1的构造函数中获得MyClass1。
final修饰符保证了lock的安全发布,这是没有final所不能做到的。
此外,如果它不是final,它可能会被更改,从而导致您锁定了错误的对象实例。
您可以在Java Language Specification Section 17.5 ("Final Field semantics")的第17章(“线程和锁”)中找到更多关于final修饰符在安全发布方面提供的保证的信息。
发布于 2018-03-05 15:50:12
当然,它会工作的--直到您重新分配它。如果lock不是最终的,有人可以给它赋另一个值(lock = new Object())。这就像更换门上的锁一样:如果你仍然有旧钥匙,你就不能再使用锁了。
将lock设为final将防止这种情况发生,因此这样做总是一个好主意。
发布于 2018-03-05 16:05:16
基本上,您必须确保一旦创建了锁对象,就没有人会以任何方式搞乱它。因此,您必须让它成为constant,我们使用static final来做到这一点。So, by creating a constant we are making sure that our lock object is created as soon as the class is loaded and never modify that in application lifetime.
Bonus
做同样事情的另一种方法是使用static initializer。这非常适合您希望在多个语句中进行锁对象赋值的情况。下面是一个相同的示例:
public class Test {
private static final Test lockObject;
static {
System.out.println("Hello");
lockObject = new Test();
}
public static void main(String[] args) {
synchronized (lockObject) {
//your code goes here
}
}
}https://stackoverflow.com/questions/49105590
复制相似问题