A spinlock mutex can be implemented in userspace using an atomic_flag.
一旦标识对象初始化完成,只能做三种操作:销毁、清除或设置并查询其先前的值。
这些分别对应析构函数、clear()函数以及test_and_set()函数。
clear和test_and_set操作都可以指定一个内存顺序,
clear是清除操作(atomically sets flag to false),
test_and_set是读改写操作(atomically sets the flag to true and obtains its previous value)
c++20 引入了 test 操作,即读数据操作(atomically returns the value of the flag)
1 #include <thread> 2 #include <vector> 3 #include <iostream> 4 #include <atomic> 5 6 inline void cpu_relax() { 7 #if defined(__aarch64__) 8 asm volatile("yield" ::: "memory"); 9 #else 10 asm volatile("rep; nop" ::: "memory"); 11 #endif 12 } 13 14 std::atomic_flag lock = ATOMIC_FLAG_INIT; 15 16 void f(int n) 17 { 18 for (int cnt = 0; cnt < 100; ++cnt) { 19 while (lock.test_and_set(std::memory_order_acquire)) // acquire lock 20 cpu_relax(); // spin 21 std::cout << "Output from thread " << n << ' '; 22 lock.clear(std::memory_order_release); // release lock 23 } 24 } 25 26 int main() 27 { 28 std::vector<std::thread> v; 29 for (int n = 0; n < 10; ++n) { 30 v.emplace_back(f, n); 31 } 32 for (auto& t : v) { 33 t.join(); 34 } 35 }