Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which implementations of Condition do not require current thread to hold the lock?

Recently I read some examples from the Chapter 8 of the The Art of Multiprocessor Programming, about “Monitors and Blocking Synchronization” that use the signalAll() of a Condition object, without the acquisition of the lock associated with that Condition.

Surprisingly I did not find any fix for those examples in the book’s errata. Moreover they propose a correction for the example of figure 8.12 of a FifoReadWriteLock, but they keep using the signalAll() without the lock held. That perturbed me and I tried to find other considerations about these examples to understand the reasons why these Java examples were written in this way.

For instance, the answer to the question “How does a read-write mutex/lock work?” shows the same example of the implementation of a FifoReadWriteLock, which implements the writeUnlock() as:

void writeUnlock() {
    writer = false;
    condition.signalAll();
}

About the absence of the lock acquisition you can read two different reasons:

  1. only use it as pseudo code
  2. some implementation of a condition variable doesn't require that the lock be held to signal.

It is difficult to accept the first argument since the book use examples in Java and explicitly says:

The book uses the Java programming language.

About the second point, I know that the Java API in java.util.concurrent.locks.Condition states for signal() method:

An implementation may (and typically does) require that the current thread hold the lock associated with this Condition when this method is called.

If "an implementation may" only, that means that it is NOT mandatory. Yet, to the best of my knowledge I don’t find any implementation that does NOT fulfill this requirement. So I would like to know which implementations of Java Condition do not require current thread to hold the lock?

like image 897
Miguel Gamboa Avatar asked Apr 06 '16 11:04

Miguel Gamboa


1 Answers

I'm not aware of any Condition implementation in the JDK that allows waiting or signaling without owning the monitor at the same time.

Practically all of the java.util.concurrent classes rely on AbstractQueuedSynchronizer which establishes the same contract as the built-in monitor methods wait()/notify()/notifyAll() for the condition variables it provides, i.e. it requires owning the internal lock in order to allow calling await()/signal()/signalAll().

If you try a simple example using the proposed FifoReadWriteLock, you'll find that it spews a serious amount of IllegalMonitorStateExceptions courtesy of its writeUnlock() method. These exceptions disappear if you apply the lock-try-finally approach from the other methods.

While indeed owning the monitor is not absolutely required to wait or signal, often it's the preferable approach, as it saves you from racy condition reads, it shouldn't be too costly as the hand-off between the internal wait sets of the same monitor can still be done fairly efficiently, and because most often you need it for both signaling and scheduling instead of just signaling.

like image 92
Dimitar Dimitrov Avatar answered Sep 21 '22 01:09

Dimitar Dimitrov