目录
1、线程上锁的原因
1)避免未同步的数据访问;
2)避免读写一般的数据被更改;
3)避免因线程函数体内“表达式重新排列引起”的逻辑问题。
2、Mutex
互斥锁:一般用来保护共享资源。
Mutex m; 构造,建立一个未锁定的对象
M.~Mutex(); 销毁,但必须未锁定
M.lock(); 上锁
M.try_lock(); 上锁,成功返回true
M.try_lock_until(tp); 在时间点tp前锁住,成功返回true
M.try_lock_for(dur); 在时间段dur内锁住,成功返回true
M.unlock(); 解锁
M.native_handle(); 为了不具有可移植性的扩展
3、Lock_guard<>
在该对象的生命周期结束时,自动释放对象。解决未解锁就跳出函数,不在进行解锁行为造成的异常。
4、Unique_lock<> 同上,但多三个构造函数
unique_lock l; 创建一个不关联的mutex
unique_lock l(m); 为mutex建立一个lock_guard
unique_lock l(m,adopt_lock); 为已锁定的mutex建立一个lock_guard
unique_lock L(m,defer_lock); 为mutex建立一个lock_guard但不锁定它
unique_lock l(m,try_lock); 为mutex建立一个lock_guard并试图锁住他
unique_lock l(m,dur); 为mutex建立一个lock_guard并试图锁在时间段dur内锁住他
unique_lock k(m,tp); 为mutex建立一个lock_guard并试图锁在时间点tp前锁住他
unique_lock l(rv); Move 构造
L.~Unique_lock (); 解锁并销毁
unique_lock l= rv; Move assignment
swap(l1,l2); 交换lock
L1.swap(l2); 交换lock
L.release(); 返回一个pointer指向关联的mutex并释放之
L.owns_lock(); 如果关联的mutex被锁定,返回true
if(l); 检查关联的mutex是否被锁定
L.mutex(); 返回pointer指向关联的mutex
L.lock(); 锁住关联的mutex
L.try_lock(); 尝试上锁,成功返回true
L.try_lock_for(dur); 尝试在时间段内上锁,成功返回true
L.try_lock_until(tp); 尝试在时间点tp前上锁,成功返回true
L.unlock(); 解除关联的mutex
5、区别
序号 | 操作 | Mutex | Recursive_mutex | Timed_mutex | Recursive_timed_mutex |
1 | Lock() | 捕获mutex(若无捕获阻塞) | |||
2 | Try_lock() | 捕获mutex(若无捕获返回false) | |||
3 | Unlock() | 解除mutex | |||
4 | Try_lock_for() | - | - | 试图在时间段内捕获lock | |
5 | Try_lock_until() | - | - | 试着在时间点前捕获lock |
6、测试代码
#include <iostream>
#include <thread>
#include <mutex>
#include <future>
#include <condition_variable> //使用条件变量必须包含该头文件和mutex
using namespace std;
mutex valMutex;
recursive_mutex reMutex;
void Mutex_Print(const string & s)
{
valMutex.lock();
//试图上锁。已经上锁返回0
cout << "Mutex_Print " << valMutex.try_lock() << ends;
for (char c : s)
{
cout.put(c);
}
cout << endl;
valMutex.unlock();
}
void lock_guard_Print(const string & s)
{
lock_guard<mutex> lg(valMutex);
cout << "lock_guard_Print" << ends;
for (char c : s)
{
cout.put(c);
}
cout << endl;
}
void unique_lock_Print(const string & s)
{
valMutex.lock();
//为已经锁定的mutex建立一个lock_guard
unique_lock<mutex> lg(valMutex,adopt_lock);
cout << "unique_lock_Print " << ends;
for (char c : s)
{
cout.put(c);
}
cout << endl;
}
void testDeadlock_mutext()
{
valMutex.lock();
cout << " Using mutex to test deadlock." << endl;
valMutex.unlock();
}
void testDeadlock_recursive_mutex()
{
reMutex.lock();
cout << " Using recursive_mutex to test deadlock." << endl;
reMutex.unlock();
}
int main()
{
//测试Mutex锁
auto f1 = async(launch::async, Mutex_Print, "123465789");
auto f2 = async(launch::async, Mutex_Print, "JQKA");
//测试lock_guard<> 自动解锁功能
auto f3 = async(launch::async, lock_guard_Print, "123465789");
auto f4 = async(launch::async, lock_guard_Print, "JQKA");
//测试unique_lock<> 自动解锁功能
auto f5 = async(launch::async, unique_lock_Print, "123465789");
auto f6 = async(launch::async, unique_lock_Print, "JQKA");
//测试死锁
{
#if 0
//连续锁两次会崩
lock_guard<mutex> lg(valMutex);
testDeadlock_mutext();
#else
//允许同一时间内,多次被同一个线程获取lock
lock_guard<recursive_mutex> lg(reMutex);
testDeadlock_recursive_mutex();
#endif
}
system("pause");
}