lock_guard
内部构造时相当于lock,析构时相当于执行unlock。
简单但不如lock()和unlock()灵活,通过大括号来实现,控制生命周期。
unique_lock
std::unique_lock要比std::lock_guard功能更多,有更多的成员函数,更灵活。
但是更灵活的代价是占用空间相对更大一些且相对更慢一些。
std::adopt_lock
adopt 通过,采取
表示mutex在此之前已经被上锁,不需要再lock了。
注意,必须提前lock。
std::unique_lock::try_lock/std::try_to_lock
尝试去加锁,如果没有锁定成功,会立即返回,不会产生阻塞。
前提:不能提前lock();
应用:防止其他的线程锁定mutex太长时间,导致本线程一直阻塞。
std::defer_lock
defer 延迟
功能:初始化了一个没有加锁的mutex
应用:不给它加锁的目的是以后可以调用unique_lock的一些方法。
前提:不能提前lock。
std::unique_lock::owns_lock()
当mutex被unique_lock上锁,且mutex没有解锁或析构,返回真,否则返回false。
不可复制。但是它是可以转移的(std::move)
/**
* By kkmd66
*
* 代码演示
* 1、lock()、unlock()成对使用,返回时忘记的情况
* 2、lock_guard的使用
* 3、std::adopt_lock
* 4、std::defer_lock
* 5、std::try_to_lock
* 6、std::unique_lock::release
* 7、转移互斥锁所有权
*/
#include "iostream"
//多线程的头文件
#include "thread"
#include "list"
//互斥锁的头文件
#include "mutex"
using namespace std;
#define USE_LOCK_UNLOCK
#define USE_LOCKGUARD
#define USE_UNIQUELOCK
#define USE_ADOPTLOCK //已经提前lock
#define USE_DEFER_LOCK //互斥量没有lock,不能提前lock,只能后面lock
#define USE_TRY_TO_LOCK //尝试去lock(不能提前lock),lock失败会返回,防止阻塞
#define USE_RELEASE //解除所有权
#define USE_MOVE //移除所有权
class DealData {
public:
void putInData() {
//数字增大可以增加冲突概率
for (int i = 0; i < 1000; ++i) {
#ifdef USE_LOCK_UNLOCK
myMutex.lock();
cout << "putInData 子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
myMutex.unlock();
#endif //USE_LOCK_UNLOCK
#ifdef USE_LOCKGUARD
lock_guard<mutex> dataGuard(myMutex);
cout << "putInData 子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
#endif // USE_LOCKGUARD
#ifdef USE_UNIQUELOCK
unique_lock<mutex> dataOutUnique(myMutex);
cout << "putInData 子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
#endif //USE_UNIQUELOCK
#ifdef USE_ADOPTLOCK
//使用std::adopt_lock 必须先lock
myMutex.lock();
unique_lock<mutex> dataControl(myMutex, std::adopt_lock);
cout << "putInData子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
#endif //USE_ADOPTLOCK
#ifdef USE_DEFER_LOCK
//std::defer_lock 使用myMutex没有加锁
unique_lock<mutex> dataControl(myMutex, std::defer_lock);
myMutex.lock();
//处理共享代码
cout << "putInData子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
myMutex.unlock();
//处理非共享代码
//....
//使用try_lock功能类似try_to_lock
if (myMutex.try_lock() == true) {
//如果拿到了锁
cout << "putInData子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
} else {
//如果没有拿到锁
cout << "putInData 子线程:没拿到锁" << i << endl;
}
#endif //USE_DEFER_LOCK
#ifdef USE_TRY_TO_LOCK
//使用std::try_to_lock之前不能lock,否则会lock两次出错
unique_lock<mutex> dataControl(myMutex, std::try_to_lock);
if (dataControl.owns_lock()) {
//如果拿到了锁
cout << "putInData子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
} else {
//如果没有拿到锁
cout << "putInData 子线程:没拿到锁" << i << endl;
}
#endif //USE_TRY_TO_LOCK
#ifdef USE_RELEASE
//把dataControl和myMutex绑定在一起,dataControl有myMutex的所有权
unique_lock<mutex> dataControl(mutex);
//释放了dataControl对myMutex的所有权,由pControl接管
std::mutex *pControl = dataControl.release();
cout << "putInData子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
pControl->unlock();
//非共享数据
//....
#endif //USE_RELEASE
#ifdef USE_MOVE
unique_lock<mutex> dataControl1(myMutex);
//unique_lock<mutex> dataControl2(dataControl1); //不能复制所有权
unique_lock<mutex> dataControl2(std::move(dataControl1)); //可以移动所有权
cout << "putInData子线程:放入一个数据" << i << endl;
dataQuene.push_back(i);
#endif //USE_MOVE
}
}
void takeOutData() {
while (1) {
bool res = haveDta();
}
}
//为了演示lock()、unlock()配对的重要性
bool haveDta() {
#ifdef USE_LOCK_UNLOCK
myMutex.lock();
if (!dataQuene.empty()) {
cout << "takeOutData子线程:取出一个数据" << dataQuene.front() << endl;
dataQuene.pop_front();
myMutex.unlock(); //不能忘记
return true;
}
myMutex.unlock();
return false;
#endif //USE_LOCK_UNLOCK
#ifdef USE_UNIQUELOCK
unique_lock<mutex> dataOutUnique(myMutex);
if (!dataQuene.empty()) {
cout << "takeOutData 子线程:取出一个数据" << dataQuene.front() << endl;
dataQuene.pop_front();
return true;
}
return false;
#endif //USE_UNIQUELOCK
#ifdef USE_TRY_TO_LOCK
unique_lock<mutex> dataControl(myMutex);
std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (!dataQuene.empty()) {
cout << "takeOutData 子线程:取出一个数据" << dataQuene.front() << endl;
dataQuene.pop_front();
return true;
}
return false;
#endif //USE_TRY_TO_LOCK
//DEFAULT
unique_lock<mutex> dataOutUnique(myMutex);
if (!dataQuene.empty()){
cout << "takeOutData 子线程:取出一个数据" << dataQuene.front() << endl;
dataQuene.pop_front();
return true;
}
return false;
}
private:
std::list<int> dataQuene;
mutex myMutex;
};
int main() {
// std::list<int> dataQuene;
//1、创建并开启线程,线程入口是putInData, takeOutData 函数
DealData myData;
thread putThread(&DealData::putInData, ref(myData));
thread takeThread(&DealData::takeOutData, ref(myData));
takeThread.join();
putThread.join();
return 1;
}
最后
有问题欢迎与我联系~
vx:kkmd66-2