Thread Mutex
- std::mutex 是 C++11 最基本的互斥量,该类的实例化对象提供了资源独占所有权的特性,用于保护共享数据免受多个线程同时访问的同步原语。
Mutex
用法
- 头文件
- 类型
- std::mutex
- std::recursive_mutex
- std::time_mutex
- std::recursive_time_mutex
- 操作
- 加锁
- 解锁
- 查看是否上锁
- trylock
- 未上锁,返回 false,并锁住
- 其他线程已上锁,返回 true
- 同一线程已经上锁,将会产生死锁
代码
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int g_resource_printer = 4;
mutex mx;
void person_1()
{
mx.lock();
g_resource_printer++;
this_thread::sleep_for(chrono::seconds(2));
cout << "Thread_1 using printer.... g_resource_printer : " << g_resource_printer << endl;
mx.unlock();
}
void person_2()
{
mx.lock();
g_resource_printer--;
this_thread::sleep_for(chrono::seconds(2));
cout << "Thread_2 Using printer.... g_resource_printer : " << g_resource_printer << endl;
mx.unlock();
}
int main()
{
thread thread1(person_1);
thread thread2(person_2);
thread1.join();
thread2.join();
return 0;
}
lock_gurad
介绍
- 会在实例化时去获取一个 mutex 的所有权,在作用域消失时,会自动析构并释放 mutex
- 创建即加锁,作用域结束自动析构并解锁,无需自动解锁
- 不能中途解锁,也不支持手动解锁
- 不能复制
代码
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex g_mtx;
int g_resource = 1;
void proc_1()
{
lock_guard<mutex> lk(g_mtx);
// the code for handling shared resources
g_resource++;
cout << "Proc 1 : " << g_resource << endl;
}
void proc_2()
{
lock_guard<mutex> lk(g_mtx);
g_resource--;
cout << "Proc 2 : " << g_resource << endl;
}
int main()
{
thread thread1(proc_1);
thread thread2(proc_2);
thread1.join();
thread2.join();
return 0;
}
unique_lock
介绍
- 创建时可以不锁定,在需要的再锁定
- 可以手动的,随时加锁解锁
- 作用域结束后,析构函数自动释放锁
- 不可复制,可移动
- 条件变量需要该类型的锁作为参数(此时必须使用 unique_lock)
代码
#include <iostream>
#include <thread>
#include <mutex>
struct Box
{
explicit Box(int num) : num_thing(num){}
int num_thing;
std::mutex m;
};
void transfer(Box& from, Box &to, int num)
{
// std::defer_lock means locks later
std::unique_lock<std::mutex> lock1(from.m, std::defer_lock);
std::unique_lock<std::mutex> lock2(to.m, std::defer_lock);
std::lock(lock1, lock2); // now lock lock1 and lock2
// lock1.lock()
// lock2.lock()
from.num_thing -= num;
to.num_thing += num;
}
int main()
{
Box acc1(100);
Box acc2(200);
std::thread thread1(transfer, std::ref(acc1), std::ref(acc2), 10);
std::thread thread2(transfer, std::ref(acc1), std::ref(acc2), 20);
thread1.join();
thread2.join();
std::cout << "acc1.num_thing : " << acc1.num_thing << std::endl;
std::cout << "acc2.num_thing : " << acc2.num_thing << std::endl;
return 0;
}
总结:
- 为了解决多线程资源竞争,C++ 使用 mutex 类提供数据保护
- 为了践行RAII思想,或者说为了防止加锁后忘记解锁,使用 lock_guard
- 为了更方便的使用锁,提供 unique_lock 即保证了 RAII,又可以手动解锁