1

I need to stop thread somehow for 1 sec while thread is in critical section locked by ReentrantLock.

My code is :

public class Lock implements Runnable {
    private ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " is running !");
            lock.wait(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        Lock lock = new Lock();
        Thread thread = new Thread(lock);

        thread.start();
    }
}

When I call lock.wait(1000) in run() method it throws IllegalMonitorStateException.

Why is this exception if I obtained monitor by lock.lock() method?

The same happens when I call super.wait(1000) instead of lock.wait(1000).

Volodymyr Levytskyi
  • 3,364
  • 9
  • 46
  • 83
  • This is not what `lock.wait` does. `wait` atomically releases the `lock` and suspends the thread. This is part of the [`wait`/`notify`](http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html) API - it is inherited from `Object` and not part of `Lock`. In order to call `wait` you **must** own the monitor on the object - i.e. you must be `synchronized` on it. You are looking for `Thread.sleep`. – Boris the Spider May 19 '14 at 07:06
  • Why occurs `IllegalMonitorStateException`? – Volodymyr Levytskyi May 19 '14 at 07:07
  • Because you are in an illegal monitor state, and that's an exception. Read about `synchronized` blocks and `wait`/`notify`. This has nothing to do with `Lock` and you shouldn't be using it here. – Boris the Spider May 19 '14 at 07:09
  • synchronized is about object's implicit monitor and ReentrantLock is about mutual exclusive access to resource. – Volodymyr Levytskyi May 19 '14 at 07:23
  • 1
    @Volodia as @Boris said: if you want to sleep use `Thread.sleep()` if you insist on misusing wait you have to write it as `long startTime = System.currentTimeMillis(); synchronized (lock) { while (System.currentTimeMillis() - startTime < 1000) { lock.wait(1000); } }` – Absurd-Mind May 19 '14 at 08:18

1 Answers1

0

You get the exception when calling lock.wait(1000) inside the lock b/c you haven't got the object locked in the right way. It's a thing.

synchronized(object) {
  object.wait(1000);
}

That works b/c you have the object's monitor locked. ReentrantLock.lock() works in a different way. All is not lost! You can use Thread.sleep() or LockSupport.parkNanos() to put your thread to sleep inside the critical section.

If you need to handle spurious wakeup, you'll want a loop.

long waitStart = System.nanoTime();
long waitTime = TimeUnit.SECONDS.toNanos(1);
do {
  LockSupport.parkNanos(waitTime);
  waitTime = waitTime - (System.nanoTime() - waitStart);
} while(waitTime > 0);

Or some variation of the above.

Good luck.

Darren Gilroy
  • 2,071
  • 11
  • 6
  • i think removing the `waitTime = wait...` and `} while (System.nanoTime() - waitStart < waitTime);` would be much easier to understand. – Absurd-Mind May 21 '14 at 09:03