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

在项目中使用volatile时,为何以下两段代码运行结果不同?

Why Do These Two Volatile Code Snippets Produce Different Results?

Great question! Let's break down exactly why these two versions of your VolatileTest class behave differently when using the volatile keyword.

First, Let's Clarify What volatile Actually Does

The volatile keyword in Java gives you two key guarantees:

  • Visibility: When one thread updates a volatile variable, all other threads will immediately see the latest value (no stale cached values hanging around).
  • Instruction Reordering Prevention: It stops the JVM from rearranging instructions around the volatile variable, which keeps concurrent operations more predictable.

But here's the critical fine print: volatile does NOT make compound operations atomic.

Why the First Snippet Doesn't Hit 2000

Look at the inc++ call in your first code:

public void increase(){
    inc++;
}

Even though inc is marked volatile, inc++ isn't a single, indivisible action. It actually splits into three separate steps:

  1. Read the current value of inc from memory.
  2. Add 1 to that value.
  3. Write the new value back to memory.

With two threads running this 1000 times each, race conditions happen constantly:

  • Thread A reads inc as 300.
  • Before Thread A can write the updated 301 back, Thread B also reads inc as 300.
  • Both threads add 1, end up with 301, and write that same value back.

Instead of incrementing twice (from 300 to 302), we only increment once. These "lost updates" pile up, so the final inc value will almost always be less than 2000.

Why the Second Snippet Works Reliably

Now look at the modified increase() method with synchronized:

public synchronized void increase(){
    inc++;
}

The synchronized keyword adds two game-changing guarantees:

  • Mutual Exclusion: Only one thread can execute the increase() method at a time. Thread A has to finish the entire read-add-write sequence before Thread B can even touch inc.
  • Atomicity: The whole inc++ operation becomes a single, unbreakable step. No overlapping reads or writes mean no lost updates.

This is why the second snippet will consistently output 2000—each increment is safely isolated from concurrent modifications.

Quick Recap

  • volatile fixes visibility issues but can't protect compound operations like inc++ from race conditions.
  • synchronized solves both visibility and atomicity problems by enforcing exclusive access to the method, making multi-threaded increments safe.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:58:12