I'm trying out a simple concurrency problem from Leetcode. I've studied the topic very briefly in university, but not using the Java APIs. It seems like I can't use a ReentrantLock
(or any other Lock
to my knowledge) to solve the problem without running into an IllegalMonitorStateException
. Yet a Semaphore
(which seems like overkill, since I only need to use binary values) seems to work fine. Why is this?
Binary Semaphore vs a ReentrantLock suggests (if I understand correctly) that binary locks can only be release by the thread that acquired it, which could be the source of my issue since I am acquiring them in the constructor in my code below. Is there any other natural way to solve this problem using locks / without semaphores?
Code with Lock
s that raises IllegalMonitorStateException
:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Foo {
private Lock printedFirst;
private Lock printedSecond;
public Foo() {
this.printedFirst = new ReentrantLock();
this.printedSecond = new ReentrantLock();
printedFirst.lock();
printedSecond.lock();
}
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
printedFirst.unlock();
}
public void second(Runnable printSecond) throws InterruptedException {
printedFirst.lock();
try {
printSecond.run();
} finally {
printedSecond.unlock();
}
}
public void third(Runnable printThird) throws InterruptedException {
printedSecond.lock();
try {
printThird.run();
} finally {}
}
}
Code with Semaphore
s that works as intended:
import java.util.concurrent.Semaphore;
class Foo {
private Semaphore printedFirst;
private Semaphore printedSecond;
public Foo() {
this.printedFirst = new Semaphore(0);
this.printedSecond = new Semaphore(0);
}
public void first(Runnable printFirst) throws InterruptedException {
printFirst.run();
printedFirst.release();
}
public void second(Runnable printSecond) throws InterruptedException {
printedFirst.acquire();
try {
printSecond.run();
} finally {
printedSecond.release();
}
}
public void third(Runnable printThird) throws InterruptedException {
printedSecond.acquire();
try {
printThird.run();
} finally {}
}
}