- 不加锁实现线程安全
atomic
threadlocal:每个线程的对象共享数据,不同线程相互隔离,相当于线程内的static变量;threadlocal变量与线程绑定,和线程具有相同的生命周期,且只有第一次声明时被赋值。作用域仍然与普通变量相同。
Ref:C++11 thread_local用法、C++ 11 关键字:thread_local
CAS:CAS操作包含三个操作数——内存位置(V)、预期原值(A)、新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作。
无论哪种情况,它都会在CAS指令之前返回该位置的值。
CAS有效地说明了“我认为位置V应该包含值A;如果包含该值,则将B放到这个位置;否则,不要更改该位置,只告诉我这个位置现在的值即可”。
Ref:[锁机制及CAS实现原理(C++) ](https://zhuanlan.zhihu.com/p/400817892)
无锁数据结构
迈向多线程——解析无锁队列的原理与实现
几种典型的锁
互斥锁
5.2 互斥量
条件变量
5.3 条件变量
共享锁/读写锁
读者写者问题
自旋锁
参考:C++11:原子交换函数compare_exchange_weak和compare_exchange_strong
c++中CAS的实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| template< class T> struct atomic<T*> { public:
bool compare_exchange_weak( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ); bool compare_exchange_strong( T& expected, T desired, std::memory_order order = std::memory_order_seq_cst ); ... };
|
weak版和strong版的区别:weak版本的CAS允许偶然出乎意料的返回(比如在字段值和期待值一样的时候却返回了false),不过在一些循环算法中,这是可以接受的。通常它比起strong有更高的性能。
自旋锁的实现
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 46 47 48
|
class SpinLock { public: SpinLock() : flag_(false) {}
void lock() { bool expect = false; while(!flag_.compare_exchange_weak(expect, true)) { expect = false; } }
void unlock() { flag_.store(false); }
private: atomic<bool> flag_; };
const int kIncNum = 10000; const int kWorkerNum = 10; int sum_spinlock = 0; SpinLock spinlock;
void worker_spinlock() { for(int i = 0; i < kIncNum; i++) { spinlock.lock(); sum_spinlock++; spinlock.unlock(); } }
void test_spinlock() { vector<thread> threads; for(int i = 0; i < kWorkerNum; i++) { threads.emplace_back(worker_spinlock); }
for(int i = 0; i < kWorkerNum; i++) { threads[i].join(); }
cout << "sum_spinlock = " << sum_spinlock << endl; }
|