What is the use of creating a "Lock" class (which extends Object and does nothing)?

Hi everyone, when I use the synchronized operator, I often use this pattern:

private static Object lock = new Object(); public void F(){ //.. synchronized (lock){ //.. } //.. } 

However, in the source java.lang.Reference , I see that they use this template instead:

 static private class Lock { }; private static Lock lock = new Lock(); public void run() { //.. synchronized(lock){ //.. } //.. } 

I was wondering what is the benefit of declaring a new Lock class (which basically extends Object and does nothing)?

Or rather, why they simply did not use private static Lock lock = new Object(); ?

+7
source share
3 answers

The following code:

 synchronized(lock){ } 

doesn't actually use Lock mechanics, you just use the built-in synchronization functions on Object . In this case, you can use a plain old Object . The advantage of a lock object extending Object is that it appears in the debugging tools with the class name, and not just with the regular Object , which is more useful when looking for deadlocks.

See here for API Lock .

The advantage of Lock is that you get more options, for example, the ability to "try" to lock, and then continue to execute code if it fails. In addition, it has different properties than a synchronized block, because it is not reentrant (a thread cannot hold several locks in one lock, and then release them). If you want something like this, use ReentrantLock .

You also have cooler locks, such as ReentrantReadWriteLock , that support multiple readers, but as soon as the writer locks it, no readers are allowed. There is a large blocking ecosystem for various types of applications.

+5
source

I was wondering what is the benefit of declaring a new Lock class (which basically extends Object and does nothing)?

readability. I believe that instantiating an Object is at least strange, so having a separate, well-named class for this purpose seems like a good idea.

The BTW field containing the lock should always be final , otherwise you are asking for problems.

+4
source

The class name of the lock object appears in the stream dumps. This facilitates the interpretation of such dumps.

For example, here is an example using Reference.Lock . You can immediately see what kind of castle it is, and not to be confused with, say, a castle in ReferenceQueue . This was more important in earlier versions of the Sun JRE, where the hash identifier of the object was not displayed.

 "Reference Handler" daemon prio=10 tid=0x000000000068f400 nid=0xbf5 in Object.wait() [0x000000004055d000..0x000000004055dca0] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00007f651aa10338> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:485) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116) - locked <0x00007f651aa10338> (a java.lang.ref.Reference$Lock) 

Concerning

 private static Lock lock = new Object(); 

which does not compile (and should use final !).

+1
source

All Articles