wait() vs sleep()

Read the explanation
What if

napper sleeps inside synchronized. It stops running but keeps the lock, so other is BLOCKED the whole time.

01234567napper: enter synchronizedentersleep(1_000), holding lockBLOCKED on lockprintln

Tap any block to see what that thread is doing.

  • Holding lock
  • Blocked
Step 1/5

napper takes the lock first.

1static final Object lock = new Object();2 3static void napper() throws InterruptedException {4    synchronized (lock) {5        Thread.sleep(1_000); // sleeps, still holding the lock6    }7}8 9static void other() {10    synchronized (lock) { // BLOCKED until napper leaves11        System.out.println("other got the lock");12    }13}

Explanation

What just happened

napper went to sleep inside synchronized. A sleeping thread stops running, but it keeps every lock it holds. other needed the same lock, so it sat BLOCKED for napper’s entire nap.

Try the what-if switch

wait() releases it: lock.wait() gives up the lock and parks the thread until another thread calls notify() or notifyAll(). notifier got in at once. When waiter woke up, it had to take the lock back first, so it was briefly BLOCKED until notifier left.

The difference

Thread.sleep(ms) lock.wait()
Holds the lock? yes no, gives it up
Wakes up when time runs out notified (or timeout)
Where anywhere only inside synchronized (lock)
Belongs to Thread (static) Object

When to use which

Use sleep() to pause, never while holding a lock. Use wait() to wait for a condition another thread will make true, always in a loop:

while (!ready) lock.wait();

In modern code

wait/notify is low level and easy to get wrong. A BlockingQueue, CountDownLatch or CompletableFuture usually says what you mean more clearly. The Coordination scenarios show those.

Common questions

Does Thread.sleep() release the lock?

No. A sleeping thread keeps every lock it holds. Any thread that needs one of those locks stays BLOCKED until the sleeper wakes up and leaves the synchronized block.

Does wait() release the lock?

Yes. lock.wait() gives up that object's monitor and parks until another thread calls notify() or notifyAll(). To return from wait() it must take the lock back, so it can be briefly BLOCKED.

Why does wait() throw IllegalMonitorStateException?

wait() and notify() need the object's monitor. Call them only inside synchronized (lock) on the same object.

Does other.sleep(1000) put the other thread to sleep?

No. sleep() is static, so it always pauses the thread that calls it.

Verified: this timeline matches a real program, checked in CI on JDK 21 and 25. How we verify. Unclear or wrong? Tell us