#include <iostream>
#include <thread>
#include <vector>
using namespace std;
void myprint(int num)
{
cout << "myprint,id:" << this_thread::get_id() << endl;
}
int main()
{
// 创建和等待多个线程
vector<thread> mythreads;
// 创建10个线程,线程入口函数统一为myprint
for (size_t i = 0; i < 10; i++)
{
mythreads.push_back(thread(myprint, i));
}
for (auto &th : mythreads)
{
th.join();
}
cout << "end main" << endl;
return 0;
}
一、unique_lock取代lock_guard
unique_lock是个类模板,工作中,一般lock_guard(推荐使用);lock_guard取代了mutex的lockO和unlock()
unique_lock比lock_guard灵活很多;效率上差一点,内存占用多一点。
二:unique_lock的第二个参数
lock_guard可以带第二个参数:
std:lock_guard sbguard1(my_mutexl,std::adopt_lock);//adopt_.lock标记作用;
std:lock_guard sbguard1(my_mutexl,std::try_to_lock);//try_to_.lock标记作用;
(2.1)std:adopt_lock:表示这个互斥量已经被lock了(你必须要把互斥量提前lock了,否则会报异常)
std:adopt_lock标记的效果就是“假设调用方线程已经拥有了互斥的所有权(已经lock()成功了);
通知lock_guard不需要在构造函数中lock这个互斥量了;
unique_.lock也可以带std::adopt_.lock标记,含义相同,就是不希望再unique_.lock()的构造函数中lock这个mutex。
用这个adopt_lock的前提是,你需要自己先,把mutex先lock上:
(2.2)std:try_to_lock
我们会尝试用mutex的lockO去锁定这个mutex,但如果没有锁定成功,我也会立即返回,并不会阻塞在那里;
用这个txy_to_1ock的前提是你自己不能先去lock。
(2.3)std:defer_lock
用这个defer_1ock的前提是你不能自己先lock,否则会报异常。
defer_lock的意思就是并没有给mutext加锁:初始化了一个没有加锁的mutex
三、unique_lock的成员函数
std::unique_lock ulock(my_mutex,std::defer_lock);//没有加锁的my_mutex
ulock.lock();//不需要自己解锁
(3.1)1ock(),加锁
(3.2)unlock(),解锁;
(3.3)txy_lock(),尝试给互斥量加锁,如果拿不到锁,则返回false,如果拿到了锁,返回true,这个函数不阻塞的;
(3.4)release(),返回它所管理的mutex指针,并释放所有权;也就是说,这个unique_lock和mutex不再有关系。
严格区分unlock()和release()的区别,不要混淆
如果原来mutex对象处于加锁状态,我们有责任接管过来手动解锁。(release返回的是原始mutex的指针)
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
using namespace std;
mutex m;
void myprint(int num)
{
std::unique_lock<std::mutex> g(m);
std::mutex *pmtx = g.release(); // release后,需要我们自己解锁这个m
cout << "myprint,id:" << this_thread::get_id() << endl;
pmtx->unlock(); // 自己解锁
delete pmtx;
pmtx = nullptr;
}
int main()
{
// 创建和等待多个线程
vector<thread> mythreads;
// 创建10个线程,线程入口函数统一为myprint
for (size_t i = 0; i < 10; i++)
{
mythreads.push_back(thread(myprint, i));
}
for (auto &th : mythreads)
{
th.join();
}
cout << "end main" << endl;
return 0;
}
四、unique_lock所有权的传递
unique_lock需要管理一个mutex
unique_lock ulock(my_mutex);所有权概念
ulock拥有my_mutex的所有权
ulock可以把自己对my_mutext的所有权转移给其它的unique_lock对象;
所以,unique_lock对象这个mutex的所有权是属于 可以转移,但是不能复制的
unique_lock ulock(my_mutex);
unique_lock ulock2(my_mutex); //报错,不能复制
unique_lock ulock(move(my_mutex)); //对的
std::unique_lock<std::mutex> get_unique_lock()
{
std::unique_lock<std::mutex> tmp(m);
return tmp; // 从函数返回一个局部的unique_lock对象时可以的.返回这种局部对象tmp会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数
}
从函数返回一个局部的unique_lock对象时可以的.返回这种局部对象tmp会导致系统生成临时unique_lock对象,并调用unique_lock的移动构造函数