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

为何无同步时线程更新不可见?《Effective Java》线程序列号问题咨询

Understanding Why Another Thread Might Read 0 After Updates in Unsynced Code

Great question—this gets to a key distinction between atomicity and visibility in Java's memory model, which is super easy to mix up. Let's break this down step by step:

First: Clarify the Two Critical Concepts

You’re right that writes to int variables are atomic, but atomicity only guarantees a write operation completes without being split into smaller, interruptible parts. It does not guarantee that other threads will see that write immediately. That’s where visibility comes in—the rule that dictates when changes to a shared variable become visible to other threads.

How Java's Memory Model Explains the Behavior

Java doesn’t force threads to read/write directly to shared main memory. Instead:

  • Each thread maintains its own working memory (a local cache of variables it’s actively using).
  • When a thread reads a variable, it copies the current value from main memory to its working memory.
  • When a thread writes a variable, it updates its working memory first—and there’s no guarantee when that update gets flushed back to main memory (it could be seconds later, or never, if the thread exits before flushing).

Applying This to Your Code Snippet

Let’s walk through the scenario you described:

  1. Thread A calls generateSerialNumber() repeatedly, getting 0, 1, ..., n.
    • Each time, Thread A reads nextSerialNumber from its local working memory, increments it, and writes the new value back to its own working memory.
    • Without synchronization, Thread A never flushes these updates to main memory. The main memory still holds the initial value 0.
  2. Thread B calls generateSerialNumber() next.
    • Thread B reads nextSerialNumber directly from main memory (still 0), increments it to 1 in its own working memory, and returns 0.

So even though Thread A’s operations were atomic, Thread B never saw any of its updates because those changes were stuck in Thread A’s local cache.

Why Volatile Fixes This

If you mark nextSerialNumber as volatile:

private static volatile int nextSerialNumber = 0;
  • It forces every read of the variable to come directly from main memory (no local caching).
  • It forces every write to the variable to be immediately flushed to main memory.

This ensures visibility across threads, so Thread B would see the updated value from Thread A instead of the initial 0.

A Quick Side Note on Atomicity

Also, keep in mind that nextSerialNumber++ isn’t fully atomic—it’s a read-modify-write operation. Even with visibility, without additional synchronization (like synchronized methods or AtomicInteger), you could still get duplicate serial numbers if two threads read the same value at the same time. But your specific question is about visibility, which is why Thread B can read 0 after Thread A’s updates.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:53:36