What is Thread.yield(), and why is it rarely the right tool?
answer
- yield = advisory hint to give up the CPU
- scheduler may ignore it entirely — guarantees nothing
- static, no duration, no InterruptedException, keeps locks
- never use for correctness or fairness
- spin-loop micro-opt → prefer Thread.onSpinWait()
basics
~20 sThread.yield() is a hint that the current thread is willing to give up the CPU so other threads can run. The scheduler is free to ignore it, so it guarantees nothing and is rarely needed.
solid answer
~50 sThread.yield() is a static method that gives the scheduler an advisory hint: the current thread is willing to pause and let other ready threads of the same or higher priority run. It is purely a suggestion — the JVM/OS scheduler may ignore it entirely, may immediately reschedule the same thread, and behavior varies across platforms and JVMs. Unlike sleep(), yield does not block for a duration, does not throw InterruptedException, never releases locks, and there's no guaranteed state transition. Because it has no portable, dependable semantics, it should not be used for correctness (e.g., to 'ensure' another thread progresses) or for fairness — those need proper synchronization (locks, conditions, queues). Legitimate uses are narrow: occasionally as a micro-optimization in busy-wait/spin loops to reduce CPU burn, and in testing to provoke interleavings. In modern code, higher-level concurrency utilities or Thread.onSpinWait() are preferred.
go deeper
Knows yield is a hint to let other threads run and that the scheduler can ignore it.
Contrasts yield with sleep/wait (no duration, no exception, keeps locks, no state change) and knows it gives no guarantees.
Explains why yield must not be used for correctness or fairness, the busy-wait/visibility pitfalls, and prefers j.u.c primitives or onSpinWait() for spin loops.
Reasons about scheduler behavior across platforms, when (rarely) a spin/yield is justified vs blocking, and sets team conventions steering away from yield-based hacks toward proper concurrency abstractions.
## Background: the scheduler Many threads compete for a limited number of CPU cores. The **scheduler** (in the OS, with the JVM mapping threads onto OS threads) decides which **RUNNABLE** thread actually runs and for how long. Threads don't normally control this directly — that's the scheduler's job. ## What yield is `Thread.yield()` is a **static** method acting on the **current** thread. It is a **hint** to the scheduler: "I'm willing to give up my current turn on the CPU so other threads that are ready to run can have a go." That's the *entire* contract. ## Why "hint" is the key word The Java specification deliberately says yield is **advisory**. The scheduler is **free to ignore it completely**. Possible outcomes of calling `yield()`: - Another ready thread is scheduled (the intended effect), **or** - Nothing happens and the same thread keeps running, **or** - The same thread is immediately rescheduled even though others were ready. Behavior **differs across operating systems, JVM versions, and core counts**. There is **no guarantee** and **no defined thread-state transition** — the thread stays conceptually RUNNABLE. ## How it contrasts with sleep and wait - **`sleep(ms)`** pauses for a defined time (`TIMED_WAITING`), throws `InterruptedException`, keeps locks. yield does **none** of that — no duration, no exception. - **`wait()`** releases the monitor and waits for a notify. yield **never releases locks** and isn't tied to any object/condition. - So yield is the weakest of the three: a no-op-able scheduling nudge. ## Why it's rarely correct Because yield guarantees nothing, you can **never** rely on it for **correctness**. A classic bug is a busy-loop like `while (!ready) Thread.yield();` used to "wait" for another thread — this can spin forever on some platforms, wastes CPU, and has no memory-visibility guarantee for `ready` unless it's `volatile`/synchronized. The right tool is a real coordination primitive: `wait/notify`, `Condition`, `CountDownLatch`, `BlockingQueue`, or a `Future`. It's also a poor **fairness** tool: real fairness comes from fair locks (`new ReentrantLock(true)`) or queueing, not from politely yielding. ## The narrow legitimate uses - **Spin-wait micro-optimization:** in a tight busy-wait you *expect* to exit very soon, an occasional yield (or better, **`Thread.onSpinWait()`**, added in Java 9, which hints the *CPU* to relax in a spin loop) can reduce wasted cycles. This is an optimization, never a correctness mechanism. - **Testing/repro:** sprinkling yields can shake loose race conditions by changing interleavings. ## Practical guidance Treat `Thread.yield()` as a low-level, non-portable hint. Reach for it almost never; if you think you need it for behavior to be *correct*, you actually need synchronization. For spin loops, prefer `onSpinWait()`. Default to `java.util.concurrent` utilities, which encode correct, portable coordination.
- Why is `while(!ready) Thread.yield();` a bad way to wait for another thread?yield is only a hint and may be ignored, so it can busy-spin forever burning CPU; and without volatile/synchronization on `ready` the update may never be seen. Use wait/notify, a Condition, a latch, or a BlockingQueue instead.
- What's a modern alternative to yield inside a spin-wait loop?Thread.onSpinWait() (Java 9+), which hints to the CPU that it's in a short busy-wait so it can save power/resources, without making correctness guarantees. Better still, avoid spinning and use a blocking coordination primitive.
saying these in an interview costs you the question
- Claiming yield guarantees another thread will run — it's advisory and may be ignored.
- Using yield to 'fix' a race or ensure ordering — that's a correctness bug; use synchronization.
- Saying yield releases locks or sleeps for a time — it does neither.
- Expecting consistent yield behavior across platforms/JVMs.