You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java实例变量线程不可见问题:NoVisibility为何可能无限循环?

Understanding the NoVisibility Infinite Loop Issue

First, let's recap the classic NoVisibility example that's likely in your book—this makes it easier to walk through the problem clearly:

public class NoVisibility {
    private static boolean ready;
    private static int number;

    private static class ReaderThread extends Thread {
        public void run() {
            // This loop might run forever!
            while (!ready) {
                Thread.yield();
            }
            System.out.println(number);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        new ReaderThread().start();
        Thread.sleep(1000);
        number = 42;
        ready = true;
    }
}

Your confusion is totally valid—why would ready = true seem like it never "sticks" for the reader thread? Let's break this down step by step:

  • Thread-local caching is the core culprit
    Java's memory model lets each thread maintain its own local cache of shared variables, instead of reading/writing directly to main memory every time. This is a critical performance optimization—accessing local CPU cache is way faster than main memory.

    When the ReaderThread starts, it loads the initial value of ready (false) into its local cache. As it runs the tight while (!ready) loop, the CPU might optimize this repeated read to only check its local cache, never going back to main memory to see if the value changed.

  • No visibility guarantees without synchronization
    When the main thread sets ready = true, there's no rule (without explicit synchronization) forcing it to immediately flush that update to main memory. Even if it does eventually flush the value to main memory, there's no rule forcing the ReaderThread to discard its local cache and re-read the fresh value from main memory.

    It's not that the assignment "didn't happen"—the main thread definitely executes ready = true. The problem is that this update never becomes visible to the reader thread, thanks to the lack of synchronization rules enforcing cache consistency.

  • Why the infinite loop?
    Exactly as you suspected: the ReaderThread is stuck reading its local cache's stale false value, while the main thread's ready = true update either never makes it to main memory, or the reader thread never checks main memory again. The loop runs forever because the reader never sees the updated value.

How to fix it?

The simplest fix is to mark the ready variable as volatile:

private static volatile boolean ready;

The volatile keyword tells the JVM three key things:

  1. Every read of this variable must come directly from main memory, not the thread's local cache.
  2. Every write to this variable must be immediately flushed to main memory.
  3. No instruction reordering around reads/writes of this variable (which also ensures consistency, like making sure number = 42 is visible before ready = true).

Alternatively, you could wrap the read and write operations in synchronized blocks, which also guarantees visibility and mutual exclusion.

内容的提问来源于stack exchange,提问作者zonyang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:35:02