Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixing synchronized() with ReentrantLock.lock()

In Java, do ReentrantLock.lock() and ReetrantLock.unlock() use the same locking mechanism as synchronized()?

My guess is "No," but I'm hoping to be wrong.

Example:

Imagine that Thread 1 and Thread 2 both have access to:

ReentrantLock lock = new ReentrantLock();

Thread 1 runs:

synchronized (lock) {
    // blah
}

Thread 2 runs:

lock.lock();
try {
    // blah
}
finally {
    lock.unlock();
}

Assume Thread 1 reaches its part first, then Thread 2 before Thread 1 is finished: will Thread 2 wait for Thread 1 to leave the synchronized() block, or will it go ahead and run?

like image 718
James Jensen Avatar asked May 24 '10 23:05

James Jensen


People also ask

Is lock required for synchronized method?

If a thread wants to execute a synchronized method on a given object, first it has to get a lock of that object. Once thread got the lock then it is allowed to execute any synchronized method on that object.

What is valid about synchronized and util concurrent locks ReentrantLock in thread concurrency in Java?

In case of a synchronized keyword, a thread can be blocked waiting for a 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.

How locks are better than synchronized?

Lock framework works like synchronized blocks except locks can be more sophisticated than Java's synchronized blocks. Locks allow more flexible structuring of synchronized code.

Why do we need reentrant lock in Java?

Reentrant Locks are provided in Java to provide synchronization with greater flexibility. What are Reentrant Locks? The ReentrantLock class implements the Lock interface and provides synchronization to methods while accessing shared resources.


2 Answers

No, Thread 2 can lock() even when Thread 1 is synchronized on the same lock. This is what the documentation has to say:

Note that Lock instances are just normal objects and can themselves be used as the target in a synchronized statement. Acquiring the monitor lock of a Lock instance has no specified relationship with invoking any of the lock() methods of that instance. It is recommended that to avoid confusion you never use Lock instances in this way, except within their own implementation.

like image 177
erickson Avatar answered Oct 19 '22 06:10

erickson


The two mechanisms are different. Implementation/performance wise:

  • the synchronized mechanism uses a locking mechanism that is "built into" the JVM; the underlying mechanism is subject to the particular JVM implementation, but typically uses a combination of a raw compare-and-set operation (CAS) instruction for cases where the lock isn't contended plus underlying locking mechanisms provided by the OS;
  • the lock classes such as ReentrantLock are basically coded in pure Java (via a library introduced in Java 5 which exposes CAS instructions and thread descheduling to Java) and so is somewhat more standardised across OS's and more controllable (see below).

Under some circumstances, the explicit locks can perform better. If you look at this comparison of locking mechanisms I performed under Java 5, you'll see that in that particular test (multiple threads accessing an array), explicit lock classes configured in "unfair" mode (the yellow and cyan triangles) allow more throughput than plain synchronized (the purple arrows).

(I should also say that the performance of synchronized has been improved in more recent versions of Hotspot; there may not be much in it on the latest versions or indeed under other circumstances-- this is obviously one test in one environment.)

Functionality-wise:

  • the synchronized mechanism provides minimal functionality (you can lock and unlock, locking is an all-or-nothing operation, you're more subject to the algorithm the OS writers decided on), though with the advantage of built-in syntax and some monitoring built into the JVM;
  • the explicit lock classes provide more control, notably you can specify a "fair" lock, lock with a timeout, override if you need to alter the lock's behiour...
like image 21
Neil Coffey Avatar answered Oct 19 '22 08:10

Neil Coffey