0

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?

1
  • you know the answer buddy! you would like to make sure that nobody makes a new assignment to the lock reference variable. Commented Mar 5, 2018 at 7:49

4 Answers 4

2

Sure, it will work -- until you re-assign it. If lock is not final, somebody could assign another value to it (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.

Sign up to request clarification or add additional context in comments.

Comments

2

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.

The final modifier guarantees safe publication of the lock in a way that not having final does not.

Also, if it's not final, it could be changed, leading to you locking on the wrong object instance.

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").

3 Comments

Could you add a reference which further explains the guarantees final provides?
@Jens I think a static final gets created when the class loads. Hence, there are no chances that a thread messes it up wrt to assignement.. Hope that makes sense.
@Jens Good idea, I've added it.
0

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

Comments

0

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.

If it's not final and gets reassigned, the lock status will be irrelevant.

I'd recommend using the Lock class anyway.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.