What is Lock Interface?
Lock provides the same functionality as a synchronized block. Like synchronized, a lock is a tool for controlling access to a critical region by multiple threads.

Example using synchronized block:
class SynchronizedExample {
private Object lockObj = new Object();
public void changeData() {
synchronized(lockObj) {
//changing lot of data
//changing lot of data
}
}
}
Example using Lock class:
class LockExample {
private Lock lockObj = new ReenterantLock();
public void changeData() {
lockObj.lock();
try {
//changing lot of data
//changing lot of data
} finally {
lockObj.unlock();
}
}
}
Note: how lock() and unlock() methods are called on Lock object to secure critical region.
Why is unlock called from finally block?

Let’s say if unlock is not called from finally block, and there is a exception, that it might happen that unlock is not called at all, which means that lock is never released.
Lock lock = new ReentrantLock();
lock.lock();
try {
update object state
}
finally {
lock.unlock();
}
A point to note is that in case of synchronized, lock is automatically release if the method/block is complete or if there is an exception.

What all implementations are provided by Java for Lock interface?
Java provides two classes that implements Lock interface or we can say Java provides two types of Locks:

- ReentrantLock
- ReentrantReadWriteLock
What is ReentrantLock?
ReentrantLock class provides feature: that we can re-enter the lock again.
In the case of synchronized, if we have a thread that enters a synchronized method and from this method calls another method that is synchronized, the thread will be able to access this method. Or we can say this as thread has re-entered a lock.
In Reentrant lock, like in synchronized a thread can re-enter a lock if it already holds that lock.
Internally lock object maintains a count, and if a thread that holds the lock acquires it again, the count is incremented and when thread calls lock.unlock, then this count is decremented. Till the time lock count value is not 0, it means some thread is holding this lock.
What are different methods provided by Lock interface to acquire lock?
Different Types of Lock:
- lock()
- tryLock()
- tryLock(time)
- lockInterruptibly()
lock()
Thread calling lock() method on lockObject will acquire the lock, if no other thread have taken the lock. If some other thread is already holding the lock, then current thread will go to block state till it gets the lock.
While thread is in block state, it can’t be interrupted.

If the thread that currently owns the lock never releases it then this thread can’t get the lock and will be blocked forever. This is similar to the normal operation of the synchronized (object) { } block. The method will block while trying to get a lock on the object, when it does it proceeds.
tryLock(time)
We can call tryLock(), passing in the maximum time to wait for the lock before giving up.
Example:
public void doSomething() throws DatabaseBusyException, InterruptedException {
Lock lck = new ReentrantLock();
if (lck.tryLock(2, TimeUnit.SECONDS)) {
try {
//do something interesting
}
finally {
lck.unlock();
}
} else {
//do something else
}
}
When a thread is waiting for a lock with a time limit as here, it can be interrupted, and tryLock() throws InterruptedException.

tryLock()
A thread invoking tryLock will return immediately either successfully acquiring the lock when the lock is not owned by another thread or without acquiring it if it is already acquired by another thread.
Also, note that the tryLock method does not honor the fairness setting. It will succeed, if the lock is available, even if other threads are waiting.

Since thread returns immediately taking lock or with a status that it can’t get a lock, therefore there is no need of interruption here. Since it’s instantaneous, this method doesn’t throw InterruptedException.
lockInterruptibly ()
There is a means of making a thread wait potentially forever for the lock (like in lock() or synchronized), but still allowing it to be interruptible. The method lockInterruptibly provides this functionality.
Summary of the lock methods:
Wait | Interruptible | Non-interruptible |
---|---|---|
Forever | lockInterruptibly() | lock() |
With max time | tryLock(time, TimeUnit) | //No method provided, but if we really wanted, we could re-call tryLock() if interrupted, until the time ran out. |
No | tryLock(): If we’re not waiting, the notion of interruptibility doesn’t apply! |
What does getQueueLength( ) method do?
Returns an estimate of the number of threads waiting to acquire this lock. The value is only an estimate because the number of threads may change dynamically while this method traverses internal data structures.
Which provides better performance when there are so many threads: synchronized or Lock?
Lock implementations ReentrantLock or ReadWriteLock provides better performance as they use CAS (Compare & Set) internally. Since Lock using CAS, this means it is a non-blocking algorithm.
What is Fair and Unfair Lock?
ReentrantLock constructor takes a boolean parameter, that lets you choose whether you want a fair or an unfair lock.
- A fair lock is one where the threads acquire the lock in the same order they asked for it.
- In case of an unfair lock a thread can sometimes acquire a lock before another thread that asked for it first.

Note: however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock.
Why we need unfair lock?
The fairness guarantee for locks comes at a significant performance cost. Fair locks will have much lower throughput than unfair locks.
What should we be using fair lock or unfair lock?
As a default, you should set fair to false unless it is critical for your logic.
What about synchronization, are built-in monitor locks fair?
The answer is, to the surprise of many that they are not. And no one complained about it, because the JVM ensures that all threads get the lock today or tomorrow.

What is the difference between Synchronized and Lock?
synchronized | lock |
---|---|
Syncronized always provide exclusive access to a resource. This means that only one thread is allowed to take a lock no matter what | Lock interface have two implementation: ReenterantLock and ReadWriteLock. ReenterantLock behaves similar to synchronized when if we are talking about exclusive access. But in case of ReadWriteLock, concurrent read access is allowed to a shared resource. |
In case of synchronized, the order in which one thread takes a lock, it should release the locks in same order. For example, if thread T1 have taken lock A, B and C, then it should release lock in order: C, B and A. | In this case, this is not necessary. |
Threads waiting for lock to be released can’t be interrupted | Threads waiting for lock can be interrupted. |
Trying to get lock is always blocking statement | Trying to acquire lock can be non-blocking (polling for lock) and can be timeout statements |
Locking is always unfair | Locking can be fair or unfair |
Performance degrades when number of threads are more | Provides good performance when number of threads are more |
It is impossible to forget to release lock, as this is done automatically | We have to specially write lock.unlock() |
JVM is able to add information related to locking when thread dumps are generated | JVM doesn’t have info about lock objects, and hence this info is not present when thread dumps are generated |
0 Comments