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

Java多线程中AtomicReference为何无法避免User.count的竞态条件?

Why AtomicReference Isn't Fixing Your Race Condition

Hey there, let's unpack what's going on here—you're not alone in mixing up what AtomicReference actually guarantees!

First, the core issue: You're using AtomicReference the wrong way

AtomicReference only ensures atomicity for the object reference itself, not the fields inside the object it points to. Let's break down your thread's operation step by step to see the race condition:

When each thread runs userRef.get().count += 1, it's actually doing three separate, non-atomic steps:

  • Call userRef.get() to fetch the current User object (this part is atomic, but that's where AtomicReference's job ends).
  • Read the current value of count from that User object.
  • Increment the value and assign it back to count (and since Integer is immutable, this creates a new Integer object under the hood).

Multiple threads can easily overlap during steps 2 and 3. For example:

  • Thread A reads count = 500
  • Thread B reads count = 500 before Thread A finishes updating it
  • Both threads increment to 501 and assign it back
  • The final count is 501 instead of 502, leading to lost increments (or in edge cases, unexpected higher values due to thread scheduling quirks with reference reassignment).

Why sync/AtomicInteger works

  • Synchronization: Wrapping the count +=1 operation in a synchronized block or method locks the entire sequence, ensuring only one thread can execute those three steps at a time. No overlaps, no lost updates.
  • AtomicInteger: This class is built specifically for atomic read-modify-write operations on integers. Methods like incrementAndGet() handle the entire cycle as a single atomic action, eliminating any window for thread interference.

How to use AtomicReference correctly (if you want to stick with it)

If you want to keep using AtomicReference for this scenario, you need to treat the entire User object as immutable and replace it entirely each time you update count. Here's what that looks like:

// Inside your thread's run method:
User currentUser;
User updatedUser;
do {
    currentUser = userRef.get();
    // Create a new User object with the incremented count
    updatedUser = new User(currentUser.count + 1);
    // CAS operation: only update the reference if it still points to currentUser
} while (!userRef.compareAndSet(currentUser, updatedUser));

This works because compareAndSet ensures we only replace the User reference if no other thread modified it since we fetched currentUser. If another thread beats us to it, we retry until we succeed.

To sum up

AtomicReference doesn't magically make all operations on the referenced object atomic—it only protects the act of swapping which object the reference points to. Your original code modified the internal state of the referenced User object, which falls outside AtomicReference's scope.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:40:04