@@ -162,17 +162,17 @@ struct trivial_type {
162
162
};
163
163
```
164
164
165
- 验证自己的类型是否满足 ` std::atomic ` 要求,我们可以这样做 :
165
+ 验证自己的类型是否满足 ` std::atomic ` 要求,我们可以使用 [ 静态断言 ] ( https://zh.cppreference.com/w/cpp/language/static_assert ) :
166
166
167
167
``` cpp
168
- std::cout << std::boolalpha << std:: is_trivially_copyable<trivial_type>::value << ' \n ' ;
169
- std::cout << std::boolalpha << std:: is_copy_constructible<trivial_type>::value << ' \n ' ;
170
- std::cout << std::boolalpha << std:: is_move_constructible<trivial_type>::value << ' \n ' ;
171
- std::cout << std::boolalpha << std:: is_copy_assignable<trivial_type>::value << ' \n ' ;
172
- std::cout << std::boolalpha << std:: is_move_assignable<trivial_type>::value << ' \n ' ;
168
+ static_assert ( std::is_trivially_copyable<trivial_type>::value, "") ;
169
+ static_assert( std::is_copy_constructible<trivial_type>::value, "") ;
170
+ static_assert( std::is_move_constructible<trivial_type>::value, "") ;
171
+ static_assert( std::is_copy_assignable<trivial_type>::value, "") ;
172
+ static_assert( std::is_move_assignable<trivial_type>::value, "") ;
173
173
```
174
174
175
- 只要全部为 ` true ` 即可 。显然我们的类型满足要求,我们可以尝试使用一下它:
175
+ 程序能通过编译即代表满足要求。如果不满足要求,静态断言求值中第一个表达式求值为 false,则编译错误 。显然我们的类型满足要求,我们可以尝试使用一下它:
176
176
177
177
```cpp
178
178
// 创建一个 std::atomic<trivial_type> 对象
@@ -191,7 +191,7 @@ std::cout << "交换前的 x: " << exchanged_value.x << ", 交换前的 y: " <<
191
191
std::cout << "交换后的 x: " << atomic_my_type.load().x << ", 交换后的 y: " << atomic_my_type.load().y << std::endl;
192
192
```
193
193
194
- > [运行](https://godbolt.org/z/eTW64nGMz )测试。
194
+ > [ 运行] ( https://godbolt.org/z/jG59c3b9M ) 测试。
195
195
196
196
没有问题,不过其实我们的 ` trivial_type ` 直接改成:
197
197
@@ -202,7 +202,7 @@ struct trivial_type {
202
202
};
203
203
```
204
204
205
- > [ 运行] ( https://godbolt.org/z/4oTf996xK ) 测试。
205
+ > [运行](https://godbolt.org/z/ozPK1qefx )测试。
206
206
207
207
也是完全可以的,满足要求。先前只是为了展示一下显式写明的情况。
208
208
@@ -295,6 +295,14 @@ void f(){
295
295
296
296
当 ` flag ` 对象的状态为设置 (` true ` ) 时,其线程调用 ` test_and_set ` 函数会返回 ` true ` ,导致它们继续在循环中自旋,无法退出。直到先前持有锁的线程调用 ` unlock() ` 函数,将 ` flag ` 对象的状态原子地更改为清除 (` false ` ) 状态。此时,等待的线程中会有一个线程成功调用 ` test_and_set ` 返回 ` false ` ,然后退出循环,成功获取锁。
297
297
298
+ > 值得注意的是,我们只是稍微的讲一下使用 ` std::atomic_flag ` 实现自旋锁。不过可没推荐各位在实践中使用它,具体可参见 ** Linus Torvalds** 的[ 文章] ( https://www.realworldtech.com/forum/?threadid=189711&curpostid=189723 ) 。其中有一段话说的很直接:
299
+ >
300
+ > - I repeat: ** do not use spinlocks in user space, unless you actually know what you're doing** . And be aware that the likelihood that you know what you are doing is basically nil.
301
+ >
302
+ > > 我再说一遍:不要在用户空间中使用自旋锁,除非你真的知道自己在做什么。请注意,你知道自己在做什么的可能性基本上为零。
303
+ >
304
+ > 然后就是推荐 ` std::mutex ` 、` pthread_mutex ` ,比自旋好的多。
305
+
298
306
` std::atomic_flag ` 的局限性太强,甚至不能当普通的 bool 标志那样使用。一般最好使用 ` std::atomic<bool> ` ,下节,我们来使用它。
299
307
300
308
## 内存次序
0 commit comments