C++多线程编程第六讲--unique_lock详解
//(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;
}
posted on 2021-10-13 08:27 xcxfury001 阅读(416) 评论(0) 收藏 举报
浙公网安备 33010602011771号