C++多线程编程第六讲--unique_lock详解
//(1)unique_lock取代lock_guard,unique_lock是一个类模板,比lock_guard更加灵活。
// lock_guard取代了mutex的lock()和unlock()。unique_lock比lock_guard效率低一点,内存占用多一些。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex); msgQueue.push_back(i); //数字i就是玩家的命令。 } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; return 0; } |
//(2)unique_lock的第二个参数
//(2.1)std::adopt_lock, 表示mutex已经lock。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); msgQueue.push_back(i); //数字i就是玩家的命令。 } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; return 0; } |
//(2.2)std::try_to_lock, 尝试用mutex的lock去加锁,如果lock不成功,也会立即返回,并不会阻塞在这里。
// 用之前不能在本线程中先lock。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex, std::try_to_lock); if (my_unique_lock.owns_lock()) { msgQueue.push_back(i); //数字i就是玩家的命令。 } else { //没拿到锁做的事情 cout << "Do not have lock" << endl; } } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); std::chrono::milliseconds dura(2000); //休息20秒 std::this_thread::sleep_for(dura); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; return 0; } |
//(2.3)std::defer_lock 不能自己先lock,否则会报异常。初始化一个没有加锁的mutex
//(3)unique_lock的成员函数
//(3.1)lock() 手动加锁,配合std::defer_lock使用,但是不必显式的解锁。
//(3.2)unlock() 解锁,可用于处理其他代码时的暂时解锁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex, std::defer_lock); //创建一个没有加锁的unique_lock my_unique_lock.lock(); //处理共享代码... my_unique_lock.unlock(); //处理非共享代码... my_unique_lock.lock(); msgQueue.push_back(i); //数字i就是玩家的命令。 } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); std::chrono::milliseconds dura(2000); //休息2秒 std::this_thread::sleep_for(dura); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; } |
//(3.3)try_lock() 尝试给互斥量加锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex, std::defer_lock); //创建一个没有加锁的unique_lock if (my_unique_lock.try_lock() == true ) { msgQueue.push_back(i); //数字i就是玩家的命令。 } else { cout << "Do not get lock." << endl; } } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); std::chrono::milliseconds dura(2000); //休息2秒 std::this_thread::sleep_for(dura); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; return 0; } |
//(3.4)release() 返回管理的mutex对象的指针,并释放所有权。unique_lock和mutex不再有关系。
// 如果原来mutex处于加锁状态,那就需要自己去解锁。人们常把锁头锁住代码的多少称为粒度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex); std::mutex* ptx = my_unique_lock.release(); //互斥量已经加锁,程序员有责任去解锁 msgQueue.push_back(i); //数字i就是玩家的命令。 ptx->unlock(); } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); std::chrono::milliseconds dura(2000); //休息2秒 std::this_thread::sleep_for(dura); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; return 0; } |
//(4)unique_lock所有权的传递
//unique_lock的所有权是可以转移的,但是不能复制。unique也是可以返回的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | #include<iostream> #include<thread> #include<vector> #include<list> #include<mutex> using namespace std; class A { public : unique_lock<mutex> rtn_unique_lock() //返回一个unique_lock { unique_lock<mutex> tmpguard(my_mutex); return tmpguard; //从函数返回一个局部的unique_lock对象是可以的,返回局部对象tmpguard //会导致系统生成临时的unique_lock对象,并且调用移动构造函数。 } public : //把收到的消息,入到一个队列中 void inMsgRecvQueue() { int i; for (i = 0; i < 100000; ++i) { cout << "push_back num = " << i << endl; //lock之后只能有一个线程可以对msgQueue队列做操作 //lock_guard<mutex> sbguard(my_mutex); unique_lock<mutex> my_unique_lock(my_mutex); unique_lock<mutex> mu_unique_lock_t(std::move(my_unique_lock)); //移动语意,my_unique_lock就为空了 msgQueue.push_back(i); //数字i就是玩家的命令 } } bool outMsgProc( int & command) { //lock_guard<mutex> sbguard(my_mutex); my_mutex.lock(); //要先lock unique_lock<mutex> my_unique_lock(my_mutex, std::adopt_lock); std::chrono::milliseconds dura(2000); //休息2秒 std::this_thread::sleep_for(dura); if (!msgQueue.empty()) { //消息不为空 command = msgQueue.front(); msgQueue.pop_front(); //移除首元素 return true ; } else { return false ; } } //把数据从消息队列中取出 void outMsgRecvQueue() { int i; int command = 0; for (i = 0; i < 100000; ++i) { int result = outMsgProc(command); if (result == true ) { cout << "command = " << command << endl; } else { cout << "msgQueue is empty" << endl; } } } private : list< int > msgQueue; mutex my_mutex; //创建一个互斥量 }; int main() { A myobj; thread myOutMsg(&A::outMsgRecvQueue, std::ref(myobj)); //保证线程中用的同一个对象 thread myInMsg(&A::inMsgRecvQueue, std::ref(myobj)); myOutMsg.join(); myInMsg.join(); cout << "main thread end..." << endl; return 0; } |
posted on 2021-10-13 08:27 xcxfury001 阅读(391) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!