Search code examples
javamultithreadingconcurrencyreentrantlock

based on which implementation does await and signalAll work


I was reading about the reentrantlock in java and how we can know the lock condition by using the newCondition() method in the interface Condition but then I saw in the documentation of the interface Condition that the user has to provide an implementation for its use.

Implementation Considerations:

The current thread is assumed to hold the lock associated with this Condition when this method is called. It is up to the implementation to determine if this is the case and if not, how to respond.

that being said since couple of days i was working on the dining philosopher problem and had to use signalAll() and await() without any self-provided implementation!.

per example i used this line:

((Philosopher) right).getNeighborCondition().await();

where the Object right is declared like this:

Iphilosopher right= new Philosopher();

Iphilosopher is an interface and the Philosopher is the class that implements it and extends Thread.

when clicking Ctrl + left mouse click on the method await() I'm presented with an interface void method which throws InterruptedException.

so which implementation is being used when await() or signalAll() are called?!


Solution

  • Your understanding of the Javadoc is slightly incorrect. Here's the section of Condition#await()'s Javadoc that you're focusing on:

    Implementation Considerations

    The current thread is assumed to hold the lock associated with this Condition when this method is called. It is up to the implementation to determine if this is the case and if not, how to respond. Typically, an exception will be thrown (such as IllegalMonitorStateException) and the implementation must document that fact.

    This is saying three things:

    1. The current thread must hold the lock when calling await(). This is further supported by the preceding documentation and the documentation of Lock#newCondition():

      Before waiting on the condition the lock must be held by the current thread.

    2. It is the responsibility of the Condition implementation to determine if the current thread holds the lock.

    3. If the current thread does not hold the lock then what should happen is left unspecified.
      • It then goes on to say that a typical implementation will throw an IllegalMonitorStateException in such cases and that whatever approach is chosen must be documented by the implementation.

    Nowhere does it say that the user must supply an implementation of Condition#await(). All it says is that the developer of a Lock, and by extension Condition, implementation must write the code to fit the contract, and provide the necessary documentation.

    You mention ReentrantLock, which is a full implementation of Lock, so let's focus on that class. Here's an excerpt from the documentation of ReentrantLock#newCondition():

    • If this lock is not held when any of the Condition waiting or signalling methods are called, then an IllegalMonitorStateException is thrown.

    This addresses point three above. This documentation states that the returned Condition instance will throw an IllegalMonitorStateException when await() (and each related method) is invoked by a thread which does not hold the lock.

    But to answer your question directly: The implementation of Condition that's being used is whatever implementation is returned by Lock#newCondition(). You're not supposed to care about what exact type is returned as that's an implementation detail. Here's some related concepts:

    If you really want to know which implementation of Condition is used you can always look at the source code1. The ReentrantLock class currently uses instances of ConditionObject.


    1. Warning: The implementations of the java.util.concurrent.locks classes are non-trivial and deal with the intricacies of concurrency. But determining the implementation of Condition used should not be too difficult.