1.介绍
std::mutex是能用于保护共享数据免受从多个线程同时访问的同步原语,是一种线程同步的手段,操作系统的学名叫互斥量。

2.特性
2.1 std::mutex 既不可拷贝亦不可移动

2.2 调用方线程在调用 lock 或 try_lock 前必须不占有 mutex 调用方线程。从它成功调用 lock 或 try_lock 开始,到它调用 unlock 为止占有 mutex 。线程占有 mutex 时,所有其他线程若试图要求 mutex 的所有权,则将阻塞(对于 lock 的调用)或收到 false 返回值(对于 try_lock ).

2.3 一般用 std::unique_lock 、 std::lock_guard 或 std::scoped_lock (C++17 起)这样更加安全的方式管理。其中前2个的区别为:
图片说明
相当于帮你自己加锁和解锁,RAII是C++一种内存管理方式,感兴趣的可以去了解下。

2.4 std::mutex对象不能被同一个线程在unlock之前多次获取,必须释放后再获取。

3.实验
不加锁时,线程可能插入执行一块代码:
图片说明
加锁之后,一定是顺序输出的:

#include <iostream>
#include <memory>
#include <string>
#include <thread>
#include <vector>
#include <mutex>
#include <random>

std::mutex g_lock;
std::uniform_int_distribution<int> g_SleepTime(1, 5);
std::mt19937 randomEngine;

void func()
{
    g_lock.lock();
    std::cout << "Current Thread: " << std::this_thread::get_id() << std::endl;
    //随机1~5秒睡眠
    std::this_thread::sleep_for(std::chrono::seconds(g_SleepTime(randomEngine)));
    std::cout << "Current Thread: " << std::this_thread::get_id() << std::endl;
    g_lock.unlock();
}

int main()
{
    std::thread t1(func);
    std::thread t2(func);

    t1.join();
    t2.join();
    //std::unique_lock<std::mutex> myLock(g_lock);
    return 0;
}

或者使用 std::unique_lock或 std::lock_guard
图片说明
就能让程序一定按顺序执行了。