@@ -216,6 +216,8 @@ struct trivial_type {
216
216
217
217
3. **Read-modify-write(读-改-写)操作**:可选的内存序包括 `memory_order_relaxed`、`memory_order_consume`、`memory_order_acquire`、`memory_order_release`、`memory_order_acq_rel`、`memory_order_seq_cst`。
218
218
219
+ > 本节主要广泛介绍 `std::atomic`,而未展开具体使用。在后续章节中,我们将更详细地讨论一些版本,如 `std::atomic<bool>`,并介绍其成员函数和使用方法。
220
+
219
221
### `st::atomic_flag`
220
222
221
223
`std::atomic_flag` 是最简单的原子类型,这个类型的对象可以在两个状态间切换:**设置(true)**和**清除(false)**。它很简单,通常只是用作构建一些库设施,不会单独使用或直接面向普通开发者。
@@ -336,7 +338,7 @@ bool new_value = (b = false); // new_value 将是 false
336
338
337
339
获取 `std::atomic<bool>` 的值有两种方式,调用 `load()` 函数,或者[隐式转换](https://zh.cppreference.com/w/cpp/atomic/atomic/operator_T)。
338
340
339
- `store` 是一个存储操作、`load` 是一个加载操作 、`exchange` 是一个“读-改-写”操作:
341
+ `store` 是一个存储操作、`load` 是一个*加载操作* 、`exchange` 是一个“* 读-改-写* ”操作:
340
342
341
343
```cpp
342
344
std::atomic<bool> b;
@@ -345,6 +347,67 @@ b.store(true);
345
347
x = b.exchange(false, std::memory_order_acq_rel);
346
348
```
347
349
350
+ ---
351
+
352
+ ` std::atomic<bool> ` 提供多个“* 读-改-写* ”的操作,exchange 只是其中之一。它还提供了一种存储方式:** 当前值与预期一致时,存储新值。**
353
+
354
+ 这种操作叫做“比较/交换”,它的形式表现为 [ ` compare_exchange_weak() ` ] ( https://zh.cppreference.com/w/cpp/atomic/atomic/compare_exchange ) 和 ` compare_exchang_strong() `
355
+
356
+ - ** compare_exchange_weak** :尝试将原子对象的当前值与预期值进行* 比较* [ ^ 1 ] ,如果相等则将其更新为新值并返回 ` true ` ;否则,将原子对象的值加载进 expected(进行加载操作)并返回 ` false ` 。** 此操作可能会由于某些硬件的特性而出现* 假失败* [ ^ 2 ] ,需要在循环中重试** 。
357
+
358
+ ``` cpp
359
+ std::atomic<bool > flag{ false };
360
+ bool expected = false;
361
+
362
+ while (!flag.compare_exchange_weak(expected, true));
363
+ ```
364
+
365
+ > [运行](https://godbolt.org/z/YToPYf3hd)测试。
366
+
367
+ 返回 `false` 即代表出现了*假失败*,因此需要在循环中重试。。
368
+
369
+ - **compare_exchange_strong**:类似于 `compare_exchange_weak`,**但不会出现假失败,因此不需要重试**。适用于需要确保操作成功的场合。
370
+
371
+ ```cpp
372
+ std::atomic<bool> flag{ false };
373
+ bool expected = false;
374
+
375
+ void try_set_flag() {
376
+ // 尝试将 flag 设置为 true,如果当前值为 false
377
+ if (flag.compare_exchange_strong(expected, true)) {
378
+ std::cout << "flag 为 false,设为 true。\n";
379
+ }
380
+ else {
381
+ std::cout << "flag 为 true, expected 设为 true。\n";
382
+ }
383
+ }
384
+ ```
385
+
386
+ > [ 运行] ( https://godbolt.org/z/zz4q8vsoe ) 测试。
387
+
388
+ 假设有两个线程运行 ` try_set_flag ` 函数,那么第一个线程调用 ` compare_exchange_strong ` 将原子对象 ` flag ` 设置为 ` true ` 。第二个线程调用 ` compare_exchange_strong ` ,当前原子对象的值为 ` true ` ,而 ` expected ` 为 ` false ` ,不相等,将原子对象的值设置给 ` expected ` 。此时 ` flag ` 与 ` expected ` 均为 ` true ` 。
389
+
390
+ 与 ` exchang ` 的另一个不同是,` compare_exchange_weak ` 和 ` compare_exchange_strong ` 允许指定成功和失败情况下的内存序。这意味着你可以根据成功或失败的情况,为原子操作指定不同的内存序。
391
+
392
+ ``` cpp
393
+ std::atomic<bool > data{ false };
394
+ bool expected = false;
395
+
396
+ // 成功时的内存序为 memory_order_release,失败时的内存序为 memory_order_acquire
397
+ if (data.compare_exchange_weak(expected, true, std::memory_order_release, std::memory_order_acquire)) {
398
+ // 操作成功
399
+ }
400
+ else {
401
+ // 操作失败
402
+ }
403
+ ```
404
+
405
+ 另一个简单的原子类型是特化的原子指针,即:** ` std::atomic<T*> ` ** ,下一节我们来看看它是如何工作的。
406
+
407
+ [ ^ 1 ] :注: 比较和复制是逐位的(类似 [ std::memcmp] ( https://zh.cppreference.com/w/cpp/string/byte/memcmp ) 和 [ std::memcpy] ( https://zh.cppreference.com/w/cpp/string/byte/memcpy ) );不使用构造函数、赋值运算符或比较运算符。
408
+
409
+ [ ^ 2 ] :注:即使 expected 与原子对象的值相等,表现如同 ` *this != expected `
410
+
348
411
### ` std::atomic<T*> `
349
412
350
413
### ` std::atomic<std::shared_ptr> `
0 commit comments