//(1)unique_lock取代lock_guard,unique_lock是一个类模板,比lock_guard更加灵活。
// lock_guard取代了mutex的lock()和unlock()。unique_lock比lock_guard效率低一点,内存占用多一些。
#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。
#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。
#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() 解锁,可用于处理其他代码时的暂时解锁。
#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() 尝试给互斥量加锁
#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处于加锁状态,那就需要自己去解锁。人们常把锁头锁住代码的多少称为粒度。
#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也是可以返回的。
#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; }