I have used the synchronized
keyword and re-entrant locks in Java, but I don't understand how they differ, or which is appropriate for a given situation.
How do I decide when should I use synchronized
and when I should use re-entrant locks?
I have used the synchronized
keyword and re-entrant locks in Java, but I don't understand how they differ, or which is appropriate for a given situation.
How do I decide when should I use synchronized
and when I should use re-entrant locks?
A ReentrantLock is:
A reentrant mutual exclusion Lock with the same basic behavior and semantics as the implicit monitor lock accessed using synchronized methods and statements, but with extended capabilities.
Extended capabilities include:
"[fair] locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order."
The disadvantages of reentrant locks are:
synchronized
keyword can be put in method definitions which avoids the need for a block which reduces nesting.Summary
The synchronized
keyword is syntactically nicer, but the Reentrant lock has more features.
This site clearly mentioned difference between ReentrantLock and synchronized keyword in Java. I just copy and paste from there.
1) Another significant difference between ReentrantLock and synchronized keyword is fairness. synchronized keyword doesn't support fairness. Any thread can acquire lock once released, no preference can be specified, on the other hand you can make ReentrantLock fair by specifying fairness property, while creating instance of ReentrantLock. Fairness property provides lock to longest waiting thread, in case of contention.
2) Second difference between synchronized and Reentrant lock is tryLock() method. ReentrantLock provides convenient tryLock() method, which acquires lock only if its available or not held by any other thread. This reduce blocking of thread waiting for lock in Java application.
3) One more worth noting difference between ReentrantLock and synchronized keyword in Java is, ability to interrupt Thread while waiting for Lock. In case of synchronized keyword, a thread can be blocked waiting for lock, for an indefinite period of time and there was no way to control that. ReentrantLock provides a method called lockInterruptibly(), which can be used to interrupt thread when it is waiting for lock. Similarly tryLock() with timeout can be used to timeout if lock is not available in certain time period.
4) ReentrantLock also provides convenient method to get List of all threads waiting for lock.
I have always thought of synchronization as "the hack of least resistance". It just works and most everyone understands how it works, but it has some weaknesses that could affect your design under heavy concurrency. Not least of which is any client effectively has direct access to your object's synchronization lock meaning if they grab it and hold it other clients can't. In other words, the locking implemented by default synchronization effectively "publishes" you object's internal locking mechanism. Yuk. Its like setting yourself up for self-inflicted denial-of-service.
If you make the reentrant lock internal to your class (or just don't use the synchronized but do something like synchronize on some internal object that you new up in your constructor everywhere that you want synchronization), you remove this side-effect of publishing your internal locking mechanism, with the added complexity of you having to remember where to apply this internal synchronization as your class evolves.