# [C++] Atomic

> 详解 C++ std::atomic 原子操作及其在多线程并发编程中的应用

作者：[汤国放](https://tonwork.fun/#person)
发布日期：2023-11-19
原文：https://tonwork.fun/blog/c-atomic/

---

### 缘由

在需要进行**并发编程**的多线程应用中，`std::atomic`会被广泛使用。

### 用法

- `load()`：从原子对象中加载当前值。

```
#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> value(10);
    int loadedValue = value.load();
    std::cout << "Loaded value: " << loadedValue << std::endl;
    return 0;
}
```

- `store(val)`：将给定的值存储到原子对象中。

```
#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> value;
    value.store(20);
    std::cout << "Stored value: " << value << std::endl;
    return 0;
}
```

- `exchange(val)`：交换原子对象中的值，并**返回之前的值**。

```
#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> value(30);
    int oldValue = value.exchange(40);
    std::cout << "Exchanged value: " << oldValue << std::endl;
    std::cout << "New value: " << value << std::endl;
    return 0;
}
```

- `compare_exchange_weak(expected, desired)` 和 `compare_exchange_strong(expected, desired)`：比较原子对象的当前值和期望值，如果相等则用新值替换当前值。

```
#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> value(50);
    int expected = 50;
    int desired = 60;
    bool success = value.compare_exchange_weak(expected, desired);
    if (success) {
        std::cout << "Compare_exchange successful. New value: " << value << std::endl;
    } else {
        std::cout << "Compare_exchange failed. Current value: " << value << std::endl;
    }
    return 0;
}
```

5. `fetch_add(val)` 和 `fetch_sub(val)`：分别对原子对象的值进行加法和减法操作，并返回操作之前的值。

```
#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> value(70);
    int oldValue = value.fetch_add(5);
    std::cout << "Old value: " << oldValue << std::endl;
    std::cout << "New value: " << value << std::endl;
    return 0;
}
```

6. `fetch_and(val)`、`fetch_or(val)` 和 `fetch_xor(val)`：分别对原子对象的值进行按位与、按位或和按位异或操作，并返回操作之前的值。

```
#include <iostream>
#include <atomic>

int main() {
    std::atomic<int> value(15);
    int oldValue = value.fetch_and(3);
    std::cout << "Old value: " << oldValue << std::endl;
    std::cout << "New value: " << value << std::endl;
    return 0;
}
```

### 作用

1. **保证原子性操作**：`std::atomic` 可以确保基本的内存读取、写入和其他操作是原子的，这意味着在多线程环境下，对 `std::atomic` 类型的对象进行操作时**不会发生数据竞争**，从而避免了需要额外的锁来保护这些操作的情况。

3. **提供内存顺序保证**：`std::atomic` 也提供了内存顺序保证，确保所有线程都能够看到相同的操作顺序，从而避免了由于指令重排等导致的意外行为。

5. **用于并发数据结构**：`std::atomic` 在开发并发数据结构时非常有用，比如并发队列、栈、哈希表等，它可以确保在多线程环境下对这些数据结构的操作是线程安全的。最好还是用lock\_guard搭配mutex来处理vector等STL容器。

7. **提高性能**：相比使用锁（如互斥锁）来进行同步，`std::atomic` 可能在某些情况下具有更好的性能，特别是对于一些简单的操作，因为它们不涉及线程的阻塞和唤醒。
