Files
asmhatreandClaude Sonnet 5 ff183da163 atomics: Java Atomics and VarHandle companion code
AtomicLong/LongAdder/VarHandle counters benchmarked against the synchronized
and ReentrantLock baselines from the locks module, a deterministic ABA race
against a hand-rolled Treiber stack plus the AtomicStampedReference fix, and
a VarHandle access-modes demo (plain/opaque/acquire-release/volatile).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01FhzLY5p6okFva3qsnsRyvM
2026-09-30 06:23:03 +00:00

22 lines
1.3 KiB
Plaintext

$ java -cp target/classes com.ankurm.atomics.AbaProblemDemo
=== Part 1: a real ABA race against TreiberStack ===
Initial stack (top first): [A, B, C]
Main thread popped, legitimately: "A", then "B"
Stack after those two real pops: [C]
Main thread pushed the SAME "A" node object back: [A, C]
Thread 1's stale CAS result: CAS succeeded, pop() would have returned "A"
Stack contents after Thread 1's stale CAS: [B, C]
"B" is back in the stack even though the main thread already popped it and
nobody ever pushed it again - Thread 1's CAS matched on reference identity
alone (top was "A" both times it looked) and blindly installed a newTop
("B") that was computed from a read that happened before two pops and a
push it never saw. "A" was also just handed out twice: once to the main
thread's first pop(), once to Thread 1's stale one.
=== Part 2: AtomicStampedReference detects the same shape of race ===
Reader captured: ref="A", stamp=0
After a concurrent A -> B -> A round trip: ref="A", stamp=2 (reference is back to "A", but the stamp moved on)
A plain AtomicReference.compareAndSet("A", "Z") would see reference == "A" and succeed: true
AtomicStampedReference.compareAndSet("A", "Z", 0, 1) actually succeeded: false (false is correct - the stamp proves a change happened in between, even though the reference alone looks unchanged)