互斥
c++通过std::mutex实现锁机制,确保多线程下只有一个进入临界区
1 2 3 4
| #include <mutex> std::mutex mtx; mtx.lock(); mtx.unlock();
|
当一个函数内需要获取多个锁时,可以采用lock同时加锁,固定加锁的顺序避免死锁
1 2 3 4 5 6 7 8 9
| lock(m1, m2); lock_guard<mutex> g1(m1, adopt_lock); lock_guard<mutex> g2(m2, adopt_lock);
|
层级锁
自定义锁添加权重来保证每次加锁顺序和解锁顺序,数值越大权重越高,核心static thread_local unsigned cur这个字段,保证了线程中多把锁存在时
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
| class hmutex { public: hmutex(unsigned val):cur(val),pre(0){} hmutex(hmutex const&) = delete; hmutex& operator=(hmutex const&) = delete;
void lock(){ if(cur <= val) std::logic_error("faild"); mtx.lock(); pre=cur,cur=val; } void unlock(){ if(cur != val) std::logic_error("faild"); cur = pre; mtx.unlock(); } private: std::mutex mtx; unsigned const val; unsigned pre; static thread_local unsigned cur; };
const unsigned HIGH = 500; cosnt unsigned MID = 300; const unsigned LOW = 100;
hmutx h1(HIGH); hmutex h2(MID); hmutex h3(LOW)
|
share_mutex
C++17新增了共享锁用来访问共享数据,实现读写锁,C++14提供share_timed_mutex,不同的是在获取锁时提供了超时机制
lock(), try_lock()
lock_shared(), try_lock_shared()
1 2 3
| std::shared_mutex mtx; std::shared_lock<std::shared_mutex> sl(mtx); std::lock_guard<std::shared_mutex> gl(mtx);
|
RAII锁
lock_guard
构造析构时自动加锁解锁,因此当中途return或退出时会自动释放锁
1 2 3
| { std::lock_guard<std::mutex> lock(mtx); }
|
c++容器不是线程安全的,因此每次操作都需要加锁
unique_lock
比lock_guard更加灵活,可以手动解锁,服务细粒度场景
支持同条件变量一起使用,一旦mutex被unique_lock管理就不能通过mutex加锁解锁
使用owns_lock()判断有无获取锁
可以延迟加锁std::unique_lock<std::mutex>(mtx,std::defer_lock)
mutex不支持移动和拷贝,但可以通过unique_lock进行转移
scope_lock
c++17新特性,可对多个互斥量同时加锁
1 2 3
| { std::scople_lock lock(mtx1, mtx2); }
|
shared_lock
到来c++14,17才有了共享锁,lock获取互斥锁,lock_shared获取共享锁
shared_mutex与shared_timed_mutex异同:
- lock两者都会阻塞直到获取锁,lock_shared则提供超时机制,