std::lock整体上是以如下步骤进行的
假设有锁m0 m1 m2 … m_end
  1. 从0索引开始lock
  2. 用try_lock对剩下的锁从m_0到m_end开始按顺序进行尝试,锁过的跳过,直到完全成功跳转到步骤5或失败于某个锁 m_i
  3. 释放之前的所有锁,调用yield放弃cpu
  4. 从m_i锁进行lock,转到步骤2
  5. 成功锁完全部,函数返回
//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//释放锁保证程序能正确退出

 

最后修改日期: 2024年10月22日

作者