乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • C++ 学习路径
  • 第1章 C++概述与开发环境

    • C++ 语言概述与编译模型
    • 第一个 C++ 程序与规范
    • 开发环境配置
    • 预处理指令详解
  • 第2章 基本语法与类型系统

    • 变量与基本类型
    • 类型转换
    • 枚举类型
    • 引用与指针
    • 数组与 stdarray
    • 字符串与原始字符串字面量
    • const 与 constexpr
    • nullptr 与空指针
    • 类型推导 auto 与 decltype
    • 基于范围的 for 循环
    • 值类别全面解析
    • char16_t 与 char32_t
    • static_assert 编译期断言
  • 第3章 函数与重载

    • 函数声明与定义
    • 函数重载
    • 默认参数与内联函数
    • Lambda 表达式
    • 函数对象与 stdfunction
    • 后置返回类型与 noexcept
  • 第4章 类与对象

    • 类的基本定义
    • 构造函数与析构函数
    • 拷贝控制
    • 移动构造函数与移动赋值
    • 列表初始化与类内初始化器
    • 静态成员与嵌套类
    • 友元
    • =default 与 =delete
  • 第5章 继承与多态

    • 继承基础
    • 虚函数与多态
    • 虚函数表与动态绑定原理
    • 虚析构函数
    • 抽象类与纯虚函数
    • 多重继承与虚继承
    • 继承构造函数
  • 第6章 运算符重载

    • 运算符重载基础
    • 算术与关系运算符重载
    • 赋值与移动运算符重载
    • 特殊运算符重载
  • 第7章 模板与泛型编程

    • 函数模板
    • 类模板
    • 模板特化与偏特化
    • 可变参数模板
    • 别名模板与模板模板参数
    • SFINAE 与类型萃取
    • 依赖名与 typename/template 关键字
  • 第8章 异常处理

    • 异常处理机制
    • noexcept 与异常安全
    • RAII 与异常安全实践
  • 第9章 内存管理与智能指针

    • 动态内存与内存分区
    • RAII 惯用法
    • unique_ptr
    • shared_ptr 与 weak_ptr
    • 内存管理最佳实践
  • 第10章 右值引用与移动语义

    • 右值引用与值类别深度解析
    • std::move 原理与使用
    • 完美转发与 std::forward
    • 移动语义性能对比与最佳实践
  • 第11章 STL容器

    • vector 深度剖析
    • deque 内部机制
    • list 与 forward_list
    • map 与 set 深度解析
    • unordered 容器与哈希原理
    • array 与 tuple
    • 容器适配器
    • 容器选择全景指南
  • 第12章 STL算法与迭代器

    • 迭代器体系全解
    • 非变异算法
    • 变异算法
    • 排序与二分算法
    • Lambda 与算法组合
    • std::random 随机数库
    • 自定义迭代器开发
  • 第13章 IO流与文件

    • 标准 IO 流
    • 格式化输出控制
    • 文件流操作
    • 字符串流
    • std::regex 正则表达式
  • 第14章 并发与多线程

    • thread 基础与线程管理
    • mutex 与 lock_guard
    • unique_lock 与 condition_variable
    • thread_local 线程局部存储
    • atomic 与内存序
    • future 与 async 异步编程
    • std::chrono 时间库
  • 第15章 现代C++新特性

    • 从 C++11 到 C++20 演进路线
    • C++14 关键新特性
    • C++17 关键新特性
    • C++20 核心特性速览
  • 第16章 面试考点与最佳实践

    • C++ 综合最佳实践清单
    • 高频面试题精讲
    • 多线程面试题与实战
    • 内存管理常见陷阱与排查
  • 附录

    • C++ 核心知识点
    • C++ 专业术语

atomic 与内存序

定义与作用

std::atomic<T> 提供不可分割的原子操作,memory_order 控制操作的同步和内存可见性。

std::atomic<int> counter{0};
counter.fetch_add(1, std::memory_order_relaxed);  // 原子递增

std::atomic<bool> flag{false};
flag.store(true, std::memory_order_release);  // 带释放语义的写入

核心原理

六种内存序

CAS(Compare-And-Swap)循环

完整示例

示例一:飞翔科技无锁统计系统

场景说明:小崔用无锁原子操作实现高性能请求统计。

#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
#include <chrono>
#include <iomanip>

struct RequestStats {
    // 原子成员
    std::atomic<uint64_t> totalRequests{0};
    std::atomic<uint64_t> successCount{0};
    std::atomic<uint64_t> errorCount{0};
    std::atomic<uint64_t> totalLatencyUs{0};  // 总延迟(微秒)
    std::atomic<uint64_t> maxLatencyUs{0};

    // 记录一次请求
    void record(bool success, uint64_t latencyUs) {
        totalRequests.fetch_add(1, std::memory_order_relaxed);

        if (success)
            successCount.fetch_add(1, std::memory_order_relaxed);
        else
            errorCount.fetch_add(1, std::memory_order_relaxed);

        totalLatencyUs.fetch_add(latencyUs, std::memory_order_relaxed);

        // 更新最大延迟(CAS 循环)
        uint64_t currentMax = maxLatencyUs.load(std::memory_order_relaxed);
        while (latencyUs > currentMax &&
               !maxLatencyUs.compare_exchange_weak(
                   currentMax, latencyUs,
                   std::memory_order_relaxed,
                   std::memory_order_relaxed))
        { /* 重试 */ }
    }

    // 快照(非原子但一致性足以满足监控需求)
    struct Snapshot {
        uint64_t total;
        uint64_t success;
        uint64_t error;
        uint64_t totalLatencyUs;
        uint64_t maxLatencyUs;
    };

    Snapshot snapshot() const {
        return {
            totalRequests.load(std::memory_order_relaxed),
            successCount.load(std::memory_order_relaxed),
            errorCount.load(std::memory_order_relaxed),
            totalLatencyUs.load(std::memory_order_relaxed),
            maxLatencyUs.load(std::memory_order_relaxed),
        };
    }
};

int main() {
    std::cout << "=== 飞翔科技无锁请求统计 ===\n\n";

    RequestStats stats;

    auto worker = [&stats](int id, int iterations) {
        // 模拟不同延迟
        uint64_t baseLatency = 100 + (id % 5) * 50;
        for (int i = 0; i < iterations; ++i) {
            bool success = (i % 10 != 0);  // 90% 成功率
            uint64_t lat = baseLatency + (i % 20);

            stats.record(success, lat);
            std::this_thread::sleep_for(std::chrono::microseconds(1));
        }
    };

    const int kThreads = 8;
    const int kIterPerThread = 5000;
    std::vector<std::thread> threads;

    auto start = std::chrono::steady_clock::now();

    for (int i = 0; i < kThreads; ++i)
        threads.emplace_back(worker, i, kIterPerThread);

    for (auto& t : threads) t.join();

    auto end = std::chrono::steady_clock::now();
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();

    auto snap = stats.snapshot();

    std::cout << std::fixed << std::setprecision(1);
    std::cout << "总请求:   " << snap.total << "\n";
    std::cout << "成功:     " << snap.success << "\n";
    std::cout << "失败:     " << snap.error << "\n";
    std::cout << "成功率:   " << (100.0 * snap.success / snap.total) << "%\n";
    std::cout << "平均延迟: "
              << (static_cast<double>(snap.totalLatencyUs) / snap.total)
              << " us\n";
    std::cout << "最大延迟: " << snap.maxLatencyUs << " us\n";
    std::cout << "耗时:     " << ms << " ms\n";
    std::cout << "吞吐量:   " << (snap.total * 1000 / ms) << " req/s\n";
}

预期输出:

=== 飞翔科技无锁请求统计 ===

总请求:   40000
成功:     36000
失败:     4000
成功率:   90.0%
平均延迟: XXX.X us
最大延迟: XXX us
耗时:     XXX ms
吞吐量:   XXXXX req/s

逐段分析:

  • fetch_add 是原子 RMW(读-改-写)操作,memory_order_relaxed 对计数器足够
  • compare_exchange_weak 实现无锁最大延迟更新,可能在虚假失败后重试
  • weak 版本可能在值匹配时也失败(spurious failure),适合循环中重试
  • strong 版本仅在值不匹配时失败,开销更大
  • 所有原子成员在 struct 中默认为零初始化

示例二:release/acquire 实现自旋锁

场景说明:大翔展示用原子布尔实现最简单的自旋锁。

#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
#include <string>

class SpinLock {
public:
    void lock() {
        // 自旋直到成功获取锁
        while (flag_.test_and_set(std::memory_order_acquire))
            ;  // 自旋等待
    }

    void unlock() {
        flag_.clear(std::memory_order_release);
    }

private:
    std::atomic_flag flag_ = ATOMIC_FLAG_INIT;
};

// 飞翔科技打印队列
SpinLock printLock;
int globalLogId = 0;

void secureLog(const std::string& msg) {
    std::lock_guard<SpinLock> lock(printLock);  // 配合自定义锁类型
    std::cout << "[" << ++globalLogId << "] " << msg << "\n";
}

void worker(int id) {
    for (int i = 0; i < 3; ++i) {
        secureLog("服务器 " + std::to_string(id) + " 心跳 #" + std::to_string(i));
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}

int main() {
    std::cout << "=== 飞翔科技自旋锁日志 ===\n\n";

    std::vector<std::thread> threads;
    for (int i = 1; i <= 4; ++i)
        threads.emplace_back(worker, i);
    for (auto& t : threads) t.join();

    std::cout << "\n所有 " << globalLogId << " 条日志完整输出\n";

    // 释放-获取语义说明
    std::cout << "\n--- 内存序说明 ---\n";
    std::cout << "lock() 中的 test_and_set(memory_order_acquire)\n";
    std::cout << "  → 后续读写不会重排到此操作之前\n";
    std::cout << "unlock() 中的 clear(memory_order_release)\n";
    std::cout << "  → 之前的写入对后续 acquire 可见\n";
    std::cout << "两者配对形成 synchronizes-with 关系\n";
}

预期输出:

=== 飞翔科技自旋锁日志 ===

[1] 服务器 1 心跳 #0
[2] 服务器 2 心跳 #0
...
所有 12 条日志完整输出

--- 内存序说明 ---
lock() 中的 test_and_set(memory_order_acquire)
  → 后续读写不会重排到此操作之前
unlock() 中的 clear(memory_order_release)
  → 之前的写入对后续 acquire 可见
两者配对形成 synchronizes-with 关系

逐段分析:

  • atomic_flag 是唯一保证始终无锁的原子类型
  • test_and_set 原子地设置为 true 并返回旧值
  • acquire 保证临界区内的操作不会重排到 lock() 之前
  • release 保证临界区内的操作在 unlock() 之前对其他线程可见
  • ATOMIC_FLAG_INIT 初始化原子标志

易错场景与面试考点

易错场景

1. atomic 不等于无锁

std::atomic<BigStruct> x;  // 可能使用内部锁而非真正的无锁
// 使用 x.is_lock_free() 检查

2. compare_exchange_weak 虚假失败

int expected = x.load();
do {
    int desired = compute(expected);
} while (!x.compare_exchange_weak(expected, desired));
// 即使 expected == x,weak 也可能失败,需要循环

3. relaxed 误用

// ❌ 用 relaxed 做同步标志
data = 42;
ready.store(true, std::memory_order_relaxed);  // 其他线程可能看不到 data=42

// ✅ 用 release/acquire
ready.store(true, std::memory_order_release);  // data 写入 happens-before
while (!ready.load(std::memory_order_acquire));  // 可见 data=42

面试考点

考点要点
atomic 保证原子性(不可分割)、可见性(多线程)、顺序性
memory_order 六种从强到弱:seq_cst, acq_rel, release, acquire, consume, relaxed
默认顺序memory_order_seq_cst,最强但开销最大
CAS 循环compare_exchange_weak/strong,无锁编程的核心模式
atomic_flag唯一保证始终无锁的类型
is_lock_free()运行时检测是否真正无锁
fetch_add/sub原子加减,返回旧值
atomic 不可拷贝拷贝构造和赋值被删除
上一页
thread_local 线程局部存储
下一页
future 与 async 异步编程