Backend Development 9 min read

How CAS Solves High-Concurrency Consistency Issues and the Hidden ABA Problem

This article examines typical high‑concurrency scenarios such as payment processing, online ordering, and cross‑bank transfers, introduces the Compare‑and‑Swap (CAS) approach to ensure strong consistency, explains the ABA problem it can cause, and presents application‑level and data‑layer strategies—including versioning and SQL examples—to mitigate it.

Architecture & Thinking
Architecture & Thinking
Architecture & Thinking
How CAS Solves High-Concurrency Consistency Issues and the Hidden ABA Problem

1 Challenges in High-Concurrency Scenarios

1.1 Typical Payment Scenario

This is the classic scenario. In the payment process, the system first queries the buyer's account balance, then calculates the product price, and finally deducts the amount. While low concurrency poses no issue, concurrent deductions can lead to consistency problems. In high‑concurrency distributed business contexts, such "query + modify" operations often cause data inconsistency.

1.2 Online Order Scenario

Similarly, when a buyer places an order on an e‑commerce platform, two actions are typically involved: inventory deduction and order‑status update. Inventory and orders usually reside in different databases, requiring distributed transactions to guarantee data consistency.

1.3 Cross‑Bank Transfer Scenario

Cross‑bank transfers are another typical distributed transaction. User A transfers 500 to User B: A's account is debited by 500, B's account is credited by 500. Since the banks are different and involve separate business platforms, a data‑consistency solution must be introduced.

2 CAS Solution

Distributed CAS (Compare‑and‑Swap) is a lock‑free approach that enables conflict‑free access to shared resources, ensuring high performance and strong data consistency, thus avoiding the problems described above.

CAS involves three basic elements: memory address V, expected old value A, and new value B. When updating a variable, the change to B occurs only if the current value at V matches the expected value A.

Using the typical payment scenario from section 1.1 as an example:

Initial balance: 800

Business 1 and Business 2 both read the balance as 800

Business 1 purchases, deducts 100, resulting in 700. The deduction should succeed only if the original balance was 800.

Business 2 pays a utility bill, deducts 200, also expecting the original balance of 800, resulting in 600. In reality, after Business 1's deduction the balance is already 600, so Business 2's concurrent deduction should fail.

According to CAS principles, when swapping the balance, a compare condition is added: the swap succeeds only if the balance remains unchanged from the initial read. This reduces read‑write lock conflicts and ensures data consistency.

3 Introducing the ABA Problem

In CAS operations, the ABA problem occurs when a thread reads a shared variable V as A, intends to change it to B, but another thread changes V from A to B and back to A. The original thread still sees A and proceeds, unaware that V has been modified.

Consequences:

1. Data consistency damage leading to business logic errors In complex business logic, shared variables often represent state or conditions. ABA can unintentionally alter these, causing issues such as overselling inventory or duplicate fund disbursement.

2. Difficult debugging and localization ABA typically occurs in multithreaded environments and is hard to detect, making troubleshooting time‑consuming.

4 Handling Strategies from Different Dimensions

The ABA issue arises because CAS only compares the value, ignoring whether the value is still the original instance. Adding a version number to each data item solves this.

Solution: CAS must compare both the value and its version; each update increments the version, preventing blind successful swaps.

4.1 Application Layer

Java's java.util.concurrent.atomic package provides tools to address ABA. In Go, the sync/atomic package is used together with versioning or timestamps. Example code:

<code>type ValueWithVersion struct {
    Value   int32
    Version int32
}

var sharedValue atomic.Value // stores *ValueWithVersion

func updateValue(newValue, newVersion int32) bool {
    current := sharedValue.Load().(*ValueWithVersion)
    if current.Value == newValue && current.Version == newVersion {
        newValueWithVersion := &ValueWithVersion{Value: newValue, Version: newVersion + 1}
        sharedValue.Store(newValueWithVersion)
        return true
    }
    return false
}
</code>

4.2 Data Layer

SQL‑level CAS strategy:

<code>UPDATE stock SET num_val = $num_new_val WHERE sid = $sid AND num_val = $num_old_val;
</code>

Combining CAS with versioning eliminates ABA:

<code># With version, no need to compare old value
UPDATE stock SET num = $num_new_val, version = $version_new WHERE sid = $sid AND version = $version_old;
</code>

5 Summary

High‑concurrency challenges: payment, ordering, cross‑bank transfer.

CAS solution and the ABA problem it may introduce.

Mitigation approaches at the application layer and data layer.

high concurrencyCASdistributed transactionsVersioningatomic operationsABA problem
Architecture & Thinking
Written by

Architecture & Thinking

🍭 Frontline tech director and chief architect at top-tier companies 🥝 Years of deep experience in internet, e‑commerce, social, and finance sectors 🌾 Committed to publishing high‑quality articles covering core technologies of leading internet firms, application architecture, and AI breakthroughs.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.