Skip to content

std::atomic 原子操作

std::atomic 提供无锁的线程安全操作,比互斥锁快 10-100x,是高性能并发的基础工具。

基本原子类型

cpp
#include <atomic>

// 常用原子类型
std::atomic<int>      ai{0};
std::atomic<bool>     ab{false};
std::atomic<uint64_t> au{0};
std::atomic<float>    af{0.0f};  // C++20 支持浮点原子操作
std::atomic<void*>    ap{nullptr};

// 原子操作
ai.store(42);                    // 写
int val = ai.load();             // 读
int old = ai.exchange(99);       // 交换,返回旧值

// 比较并交换(CAS)— 无锁算法的核心
int expected = 42;
bool ok = ai.compare_exchange_strong(expected, 100);
// 如果 ai == expected,则 ai = 100,返回 true
// 否则 expected = ai 的当前值,返回 false

// 算术操作(整数类型)
ai.fetch_add(1);   // ai += 1,返回旧值
ai.fetch_sub(1);   // ai -= 1,返回旧值
ai++;              // 等价于 fetch_add(1)
++ai;

// 位操作
ai.fetch_and(0xFF);
ai.fetch_or(0x01);
ai.fetch_xor(0x0F);

内存序

cpp
// 六种内存序(从弱到强)
std::atomic<int> x{0};

// relaxed:只保证原子性,不保证顺序(最快)
x.store(1, std::memory_order_relaxed);
x.load(std::memory_order_relaxed);

// release/acquire:建立 happens-before 关系(常用)
x.store(1, std::memory_order_release);  // 发布:之前的写对 acquire 可见
x.load(std::memory_order_acquire);      // 获取:之后的读能看到 release 之前的写

// acq_rel:同时具备 acquire 和 release(用于 RMW 操作)
x.fetch_add(1, std::memory_order_acq_rel);

// seq_cst:顺序一致性(默认,最强,最慢)
x.store(1, std::memory_order_seq_cst);
x.load(std::memory_order_seq_cst);

// 实际使用建议:
// 计数器、统计:relaxed
// 生产者-消费者标志:release/acquire
// 不确定时:seq_cst(默认)

无锁数据结构

cpp
// 无锁栈(Treiber Stack)
template<typename T>
class LockFreeStack {
    struct Node {
        T data;
        Node* next;
        Node(T d) : data(std::move(d)), next(nullptr) {}
    };

    std::atomic<Node*> head_{nullptr};

public:
    void push(T val) {
        auto* node = new Node(std::move(val));
        node->next = head_.load(std::memory_order_relaxed);
        // CAS 循环:直到成功
        while (!head_.compare_exchange_weak(
            node->next, node,
            std::memory_order_release,
            std::memory_order_relaxed));
    }

    std::optional<T> pop() {
        Node* old_head = head_.load(std::memory_order_relaxed);
        while (old_head) {
            if (head_.compare_exchange_weak(
                old_head, old_head->next,
                std::memory_order_acquire,
                std::memory_order_relaxed)) {
                T val = std::move(old_head->data);
                delete old_head;  // 注意:ABA 问题!生产代码需要 hazard pointer
                return val;
            }
        }
        return std::nullopt;
    }
};

原子标志(std::atomic_flag)

cpp
// atomic_flag 是最简单的原子类型,保证无锁
std::atomic_flag flag = ATOMIC_FLAG_INIT;

// 自旋锁实现
class SpinLock {
    std::atomic_flag flag_ = ATOMIC_FLAG_INIT;
public:
    void lock() {
        while (flag_.test_and_set(std::memory_order_acquire)) {
            // 自旋等待(可以加 CPU 暂停提示)
            #if defined(__x86_64__)
            __builtin_ia32_pause();  // x86 PAUSE 指令,减少功耗
            #endif
        }
    }
    void unlock() {
        flag_.clear(std::memory_order_release);
    }
};

// C++20 新增 test() 方法
std::atomic_flag ready = ATOMIC_FLAG_INIT;
// 线程 1
ready.test_and_set();
ready.notify_one();  // C++20:通知等待的线程

// 线程 2
ready.wait(false);  // C++20:等待直到值变为 true

实用模式

cpp
// 模式 1:引用计数(shared_ptr 的核心)
std::atomic<int> ref_count{1};

void add_ref() { ref_count.fetch_add(1, std::memory_order_relaxed); }
void release() {
    if (ref_count.fetch_sub(1, std::memory_order_acq_rel) == 1) {
        // 最后一个引用,可以销毁
        destroy();
    }
}

// 模式 2:单次初始化(double-checked locking)
std::atomic<bool> initialized{false};
std::mutex init_mtx;
ExpensiveObject* instance = nullptr;

ExpensiveObject* get_instance() {
    if (!initialized.load(std::memory_order_acquire)) {
        std::lock_guard lock(init_mtx);
        if (!initialized.load(std::memory_order_relaxed)) {
            instance = new ExpensiveObject();
            initialized.store(true, std::memory_order_release);
        }
    }
    return instance;
}

// 更简单:std::call_once
#include <mutex>
std::once_flag once;
std::call_once(once, []{ instance = new ExpensiveObject(); });

// 模式 3:进度计数器(多线程统计)
std::atomic<uint64_t> processed{0};
std::atomic<uint64_t> errors{0};

void worker() {
    // 处理任务...
    processed.fetch_add(1, std::memory_order_relaxed);
}

// 主线程定期读取(relaxed 即可,不需要精确同步)
std::cout << "已处理: " << processed.load(std::memory_order_relaxed) << "\n";

关键认知

std::atomic 的默认内存序是 seq_cst(最强),性能敏感时根据需求降级。计数器用 relaxed,生产者-消费者用 release/acquirecompare_exchange_weak 在循环中比 strong 更高效(允许伪失败)。

系统学习 C++ 生态,深入底层架构