In the previous post (Synchronized vs ReentrantLock in Java) , we have discussed the difference between synchronized and ReentrantLock. The keyword synchronized can be widely used in many multi-threaded environments. However, there are some drawbacks when using synchronized. The use of keyword synchronized provides access to the implicit monitor lock associated with every object, but forces all lock acquisition and release to occur in a block-structured way: when multiple locks are acquired they must be released in the opposite order, and all locks must be released in the same lexical scope in which they were acquired. In short, when the keyword synchronized locks a block, and a thread is in the block, other threads have to wait and will be blocked until that thread exits the block. It will slow down the performance. In some situations, it may leads to a deadlock.
Lock implementations provide more extensive locking operations than using synchronized methods and statements.
- lockInterruptibly() – Acquires the lock unless the current thread is interrupted.
- tryLock() – Acquires the lock only if it is free at the time of invocation.
- unlock() – Releases the lock
The basic implementation looks like:
1 2 3 4 5 6 7 8 9 |
Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); } |
Example using ReentrantLock
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
package net.tecbar.thread; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class LockTest { Lock lock = new ReentrantLock(); public static void main(String[] args) { final LockTest instance = new LockTest(); Thread thread0 = new Thread() { public void run() { instance.execute(Thread.currentThread()); } }; Thread thread1 = new Thread() { public void run() { instance.execute(Thread.currentThread()); } }; Thread thread2 = new Thread() { public void run() { instance.execute(Thread.currentThread()); } }; thread0.start(); thread1.start(); thread2.start(); } public void execute(final Thread thread) { lock.lock(); try { System.out.println(thread.getName() + " obtains a lock"); Thread.sleep((long) (Math.random() * 500)); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println(thread.getName() + " releases the lock"); } } } |
output:
1 2 3 4 5 6 7 8 |
Thread-0 obtains a lock Thread-0 releases the lock Thread-1 obtains a lock Thread-1 releases the lock Thread-2 obtains a lock Thread-2 releases the lock |