Skip to content

Commit f9eed73

Browse files
committedSep 27, 2024·
更新第五章 std::atomic 措辞以及补充描述
1 parent 8f46c3f commit f9eed73

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed
 

‎md/05内存模型与原子操作.md

+8-4
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ void f() {
4040

4141
### 原子类型 `std::atomic`
4242

43-
标准原子类型定义在头文件 [`<atomic>`](https://zh.cppreference.com/w/cpp/header/atomic) 中。这些类型的操作都是原子的,语言定义中只有这些类型的操作是原子的,虽然也可以用互斥量来模拟原子操作(见上文)。标准的原子的类型实现可能是:*它们几乎都有一个 `is_lock_free()` 成员函数,这个函数可以让用户查询某原子类型的操作是直接用的原子指令(返回 `true`),还是内部用了锁实现(返回 `false`)。*
43+
标准原子类型定义在头文件 [`<atomic>`](https://zh.cppreference.com/w/cpp/header/atomic) 中。这些类型的操作都是原子的,语言定义中只有这些类型的操作是原子的,虽然也可以用互斥量来模拟原子操作(见上文)。
4444

45-
> 每个 `std::atomic` 模板的实例化和全特化均定义一个原子类型。**如果一个线程写入原子对象,同时另一线程从它读取,那么行为有良好定义**(数据竞争的细节见[内存模型](https://zh.cppreference.com/w/cpp/language/memory_model))。
45+
标准原子类型的实现通常包括一个 `is_lock_free()` 成员函数,允许用户查询特定原子类型的操作是否是通过直接的原子指令实现(返回 true),还是通过锁来实现(返回 false)。
4646

47-
原子操作可以代替互斥量,来进行同步操作,也能带来更高的性能。但是如果它的内部使用互斥量实现,那么不可能有性能的提升。
47+
> **如果一个线程写入原子对象,同时另一线程从它读取,那么行为有良好定义**(数据竞争的细节见[内存模型](https://zh.cppreference.com/w/cpp/language/memory_model))。
48+
49+
原子操作可以在一些时候代替互斥量,来进行同步操作,也能带来更高的性能。但是如果它的内部使用互斥量实现,那么不可能有性能的提升。
4850

4951
在 C++17 中,所有原子类型都有一个 `static constexpr` 的数据成员 [`is_always_lock_free`](https://zh.cppreference.com/w/cpp/atomic/atomic/is_always_lock_free) 。如果当前环境上的原子类型 X 是无锁类型,那么 `X::is_always_lock_free` 将返回 `true` 。例如:
5052

@@ -101,7 +103,7 @@ else {
101103

102104
因为 `is_always_lock_free` 是编译期常量,所以我们可以使用 C++17 引入的 `constexpr if` ,它可以在编译阶段进行决策,避免了运行时的判断开销,提高了性能。
103105

104-
宏则更是简单了,最基本的预处理器判断,在预处理阶段就选择执行合适的代码
106+
宏则更是简单了,最基本的预处理器判断,在预处理阶段就选择编译合适的代码
105107

106108
在实际应用中,如果一个类型的原子操作总是无锁的,我们可以更放心地在性能关键的代码路径中使用它。例如,在高频交易系统、实时系统或者其它需要高并发性能的场景中,无锁的原子操作可以显著减少锁的开销和争用,提高系统的吞吐量和响应时间。
107109

@@ -111,6 +113,8 @@ else {
111113
2. **减少原子操作的频率**:通过批处理等技术,减少对原子操作的调用次数。
112114
3. **使用更高效的同步机制**:在一些情况下,其它同步机制(如读写锁)可能比原子操作更高效。
113115

116+
当然,其实很多时候根本没这种性能的担忧,我们很多时候使用原子对象只是为了简单方便,比如 `std::atomic<bool>` 表示状态、`std::atomic<int>` 进行计数等。即使它们是用了锁,那也是封装好了的,起码用着方便,而不需要在代码中引入额外的互斥量来保护,更加简洁。这也是很正常的需求,各位不但要考虑程序的性能,同时也要考虑代码的简洁性、易用性。即使使用原子类型无法带来效率的提升,那也没有负提升。
117+
114118
---
115119

116120
除了直接使用 `std::atomic` 模板外,也可以使用原子类型的别名。这个数量非常之多,见 [MSVC STL](https://github.com/microsoft/STL/blob/daeb0a6/stl/inc/atomic#L2745-L2805)。

0 commit comments

Comments
 (0)
Please sign in to comment.