std::lock整体上是以如下步骤进行的
假设有锁m0 m1 m2 … m_end
- 从0索引开始lock
- 用try_lock对剩下的锁从m_0到m_end开始按顺序进行尝试,锁过的跳过,直到完全成功跳转到步骤5或失败于某个锁 m_i
- 释放之前的所有锁,调用yield放弃cpu
- 从m_i锁进行lock,转到步骤2
- 成功锁完全部,函数返回
//Mutex_pf.h #pragma once #include <mutex> #include <string> class Mutex_pf { private: static int COUNT; std::mutex mutex; std::string name; public: Mutex_pf(std::string _name=""); ~Mutex_pf() = default; void lock(); void unlock(); bool try_lock(); };
//Mutex_pf.cpp #include "Mutex_pf.h" #include <iostream> using std::cout; int Mutex_pf::COUNT = 0; Mutex_pf::Mutex_pf(std::string _name) { if (_name == "") { this->name = std::to_string(COUNT++); } else { this->name = _name; } } void Mutex_pf::lock() { this->mutex.lock(); cout << std::this_thread::get_id() << " " << name << " lock\n"; } bool Mutex_pf::try_lock() { if (this->mutex.try_lock()) { cout << std::this_thread::get_id() << " " << name << " try_lock success\n"; return true; } else { cout << std::this_thread::get_id() << " " << name << " try_lock false\n"; return false; } } void Mutex_pf::unlock() { this->mutex.unlock(); cout << std::this_thread::get_id() << " " << name << " unlock\n"; }
#include <Windows.h> #include "Mutex_pf.h" template<typename T, size_t... N> auto lock_vector_core(vector<T>& vec, std::integer_sequence<size_t, N...>) { std::lock(vec[N]...); } //代理调用,简化接口,用make_integer_sequence来生成...N序列 template<typename T,size_t N> auto lock_vector(vector<T>& vec) { return lock_vector_core<>(vec, std::make_integer_sequence<size_t, N>{}); } int main() { vector<Mutex_pf> mutexs(10); int i = 2; mutexs[i].lock(); mutexs[6].lock(); std::thread t([&]() { lock_vector<Mutex_pf, 10>(mutexs); for (auto& m : mutexs) { m.unlock(); } }); Sleep(5000); mutexs[i].unlock(); Sleep(5000); mutexs[6].unlock(); t.join(); return 0; }
29172 2 lock 29172 6 lock//主线程的加锁 9360 0 lock //子线程从0开始进行lock 9360 1 try_lock success 9360 2 try_lock false //锁2失败 9360 1 unlock 9360 0 unlock//释放之前的锁 29172 2 unlock //主线程释放锁2 9360 2 lock //从锁2开始进行重新上锁 9360 0 try_lock success 9360 1 try_lock success 9360 3 try_lock success 9360 4 try_lock success 9360 5 try_lock success 9360 6 try_lock false //上面按顺序进行加锁,到锁6失败 9360 3 unlock 9360 4 unlock 9360 5 unlock 9360 0 unlock 9360 1 unlock 9360 2 unlock //释放之前的锁 29172 6 unlock //主线程释放锁6 9360 6 lock //从锁6开始lock 9360 0 try_lock success 9360 1 try_lock success 9360 2 try_lock success 9360 3 try_lock success 9360 4 try_lock success 9360 5 try_lock success 9360 7 try_lock success 9360 8 try_lock success 9360 9 try_lock success //还是按顺序来进行try_lock。这次全部成功 9360 0 unlock 9360 1 unlock 9360 2 unlock 9360 3 unlock 9360 4 unlock 9360 5 unlock 9360 6 unlock 9360 7 unlock 9360 8 unlock 9360 9 unlock//释放锁保证程序能正确退出