std::atomic_flag 用法與範例

本篇介紹 C++ 的 std::atomic_flag 用法,並提供一些範例。

atomic_flag 一個原子 bool 類型,只支援兩種函式呼叫,test-and-set 和 clear。std::atomic_flag 它保證是 lock-free 無鎖的。atomic_flag 跟 std::atomic 不同的地方在於 std::atomic_flag 不提供讀取與儲存的操作。

std::atomic_flag 請使用 ATOMIC_FLAG_INIT 定義來進行初始化,這樣可以保證 std::atomic_flag 處於 clear 的狀態。

std::atomic_flag::test_and_set() 介紹

std::atomic_flag::test_and_set() 會原子地設定 flag 的旗標為 true,並回傳 flag 之前的設定值。

std::atomic_flag::clear() 介紹

std::atomic_flag::clear() 會原子地清除 flag 旗標,設定旗標為 false,這樣會使得下一次呼叫 std::atomic_flag::test_and_set 回傳 false。

使用範例

以下範例是開3個執行緒,內部迴圈各跑15次,每次都試圖去索取 lock(atomic_flag),如果索取到的話印出該執行緒號碼與cnt第幾次,
如果沒有索取到的話,進入自旋狀態,一直 while 迴圈嘗試索取到 lock 成功為止,
test_and_set 上鎖成功會回傳 false
test_and_set 上鎖失敗會回傳 true

std-atomic_flag.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// g++ std-atomic_flag.cpp -o a.out -std=c++11 -pthread
#include <thread>
#include <vector>
#include <iostream>
#include <atomic>

std::atomic_flag lock = ATOMIC_FLAG_INIT;

void f(int n)
{
for (int cnt = 0; cnt < 15; ++cnt) {
while (lock.test_and_set(std::memory_order_acquire)) // acquire lock
; // spin 自旋
std::cout << "Output from thread " << n << ", cnt = " << cnt << std::endl;
lock.clear(std::memory_order_release); // release lock
}
}

int main()
{
std::vector<std::thread> v;
for (int n = 0; n < 3; ++n) {
v.emplace_back(f, n);
}
for (auto& t : v) {
t.join();
}

return 0;
}

輸出如下,每次執行結果不同:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Output from thread 0, cnt = 0
Output from thread 2, cnt = 0
Output from thread 0, cnt = 1
Output from thread 1, cnt = 0
Output from thread 2, cnt = 1
Output from thread 1, cnt = 1
Output from thread 2, cnt = 2
Output from thread 1, cnt = 2
Output from thread 2, cnt = 3
Output from thread 1, cnt = 3
Output from thread 2, cnt = 4
Output from thread 0, cnt = 2
Output from thread 1, cnt = 4
Output from thread 2, cnt = 5
Output from thread 0, cnt = 3
Output from thread 1, cnt = 5
Output from thread 2, cnt = 6
Output from thread 0, cnt = 4
Output from thread 2, cnt = 7
Output from thread 1, cnt = 6
Output from thread 0, cnt = 5
Output from thread 2, cnt = 8
Output from thread 0, cnt = 6
Output from thread 1, cnt = 7
Output from thread 2, cnt = 9
Output from thread 0, cnt = 7
Output from thread 2, cnt = 10
Output from thread 1, cnt = 8
Output from thread 2, cnt = 11
Output from thread 0, cnt = 8
Output from thread 2, cnt = 12
Output from thread 1, cnt = 9
Output from thread 2, cnt = 13
Output from thread 1, cnt = 10
Output from thread 2, cnt = 14
Output from thread 0, cnt = 9
Output from thread 1, cnt = 11
Output from thread 0, cnt = 10
Output from thread 1, cnt = 12
Output from thread 0, cnt = 11
Output from thread 1, cnt = 13
Output from thread 0, cnt = 12
Output from thread 1, cnt = 14
Output from thread 0, cnt = 13
Output from thread 0, cnt = 14

參考
std::atomic_flag - cppreference.com
https://en.cppreference.com/w/cpp/atomic/atomic_flag
C++11 並發指南六(atomic 類型詳解一 atomic_flag 介紹) - Haippy - 博客園
https://www.cnblogs.com/haippy/p/3252056.html
C++11中的atomic | YuanguoBlog
http://www.yuanguohuo.com/2019/07/08/cpp11-atomic/
並行編程中的lock free技術
https://blog.csdn.net/pmt123456/article/details/72844029

其它相關文章推薦
C/C++ 新手入門教學懶人包
std::thread 用法與範例
std::deque 用法與範例
std::find 用法與範例
std::mutex 用法與範例
std::unordered_map 用法與範例
std::sort 用法與範例
std::random_shuffle 產生不重複的隨機亂數
std::shared_ptr 用法與範例
std::async 用法與範例