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
就能让程序一定按顺序执行了。