简体   繁体   English

Java“静态最终”与锁定时仅“静态”变量

[英]Java “static final” vs just “static” variable while locking

I have been reading about using static objects as locks and the most common example would be something like this: 我一直在阅读有关将静态对象用作锁的信息,最常见的示例如下所示:

public class MyClass1 {
  private static final Object lock = new Object();
  public MyClass1() {
    //unsync
    synchronized(lock) {
      //sync
    }
    //unsync
  }
}

My question is does lock have to be final? 我的问题是锁必须是最终的吗? I understand it is good to put it as final to assure that nobody messes with the value, but will it work without final? 我知道最好将它设置为final,以确保没有人混淆值,但是如果没有final,它将起作用吗?

If you do not make the variable final , you may get a NullPointerException in the constructor of MyClass1 if you create the instance of MyClass1 in a different thread than the thread in which MyClass1 was loaded. 如果不把这些变量final ,你可能会得到一个NullPointerException中的构造函数MyClass1 ,如果你创建的实例MyClass1在不同的线程比,其中线状物MyClass1加载。

The final modifier guarantees safe publication of the lock in a way that not having final does not. final修饰符以没有final的方式保证安全发布lock

Also, if it's not final , it could be changed, leading to you locking on the wrong object instance. 另外,如果不是final ,则可以更改它,从而导致您锁定了错误的对象实例。

You can find out more about the guarantees that the final modifier provides in terms of safe publication in the Java Language Specification Section 17.5 ("Final Field semantics") , which is in chapter 17 ("Threads and Locks"). 您可以在Java语言规范第17.5节(“最终字段语义”) (第17章(“线程和锁”)中)中找到有关final修饰符在安全发布方面提供的保证的更多信息。

Sure, it will work -- until you re-assign it. 当然,它将起作用-直到您重新分配它为止。 If lock is not final, somebody could assign another value to it ( lock = new Object() ). 如果lock不是最终的,则有人可以为其分配另一个值( lock = new Object() )。 It's like replacing the locks in your door: if you still have the old keys, you won't be able to use the lock anymore. 这就像更换门上的锁:如果您仍然有旧钥匙,将无法再使用该锁。

Making lock final will prevent that from happening, so it's always a good idea to do it. lock final可以防止这种情况的发生,因此,这样做总是一个好主意。

Basically you have to make sure that once the lock object is created nobody messes up with it by any means. 基本上,您必须确保一旦创建了锁定对象,任何人都不会以任何方式弄乱它。 Hence, you have to make it constant which we do by using static final . 因此,您必须通过使用static final将其设置为constant 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 : 奖励

Another way of doing same is by using static initializer . 另一种方法是使用static initializer This is well suited in the cases where you wish to do the lock object assignment in more than one statements. 这非常适合您希望在多个语句中进行锁定对象分配的情况。 An example of same below: 以下是一个示例:

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
        }
    }
}

Maybe it's more intuitive if written in a different way: it's pretty much the same as this 如果以不同的方式编写,可能会更直观:与此几乎相同

public class MyClass {
    static Lock myLock = new ReentrantLock();
    public MyClass1() {
        //unsync
        myLock.lock();
        //sync
        myLock.unlock();
        //unsync
    }
}

with the same consequences of myLock being final or not. myLock是否为final相同的结果。

If it's not final and gets reassigned, the lock status will be irrelevant. 如果不是final ,而是重新分配,则锁定状态将无关紧要。

I'd recommend using the Lock class anyway. 我还是建议使用Lock类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM