This is just a note to myself and others who find it useful.
- (1) First note is on importing locks in java sdk 1.60.
- (2) Using the finally block to unlock in the end
- (3) Unlocking reentrant lock unnecessarily might result in deadlock.
- (4) Use Static statements across threads sometimes need to have “final” declaration
I tried to use a reentrant lock in a simple statement
private final Lock lock = new ReentrantLock();
I did a series of imports
import java.util.*; import java.util.concurrent.*;
But the compiler keep complaining unable to find the symbol Lock, ReentrantLock. The solution is to import the exact class
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;
I realized this after carefully examining the example here
But I am still not entirely sure why. Maybe the .* only goes one level deeper.
The second note is that we should always unlock in the finally statement. The “finally” block will execute regardless of what happens within the try lock. This ensures that the finally block is executed even if an unexpected exception occurs. It allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break.
It is the best place to do lock.unlock()
The third note is unnecessary unlocking could result in weird deadlock cases. This cost me a few hours when I did an unnecessary unlock before a return statement (there is already one unlock statement in the finally block).
The fourth note is that if I want to share a variable across different instances of the same class. I could use a static variable. However, if multiple instances exists at the same time in different threads, the variable need to be declared as “static final”. In my case, when I didn’t use the final keyword, the program would deadlock. (This is java sdk 1.60). I think some compiler would complain about it.
Your problem is that locking on a Non-Final variable reference has useless semantics.