头文件<mutex>
相比于lock_guard,更灵活,但效率上差一点,内存也占用更多.
可以看到unique_lock也含有第二个参数的构造函数.常规使用和lock_guard没什么区别。
std::try_to_lock()
std::try_to_lock()会尝试加锁,使用前不能自己lock()
使用方法如下:
class A
{
private:
list<int>msgqueue;
mutex mymutex1;
public:
void MsgEnqueue()
{
for (int i = 0; i < 10000; ++i)
{
cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
unique_lock<mutex>l(mymutex1,std::try_to_lock);
if (l.owns_lock())
{
msgqueue.push_back(i);
}
else
{
cout << "MsgEnqueue执行,但是没有拿到锁 : " << i << endl;
}
}
return;
}
bool helper(int & command)
{
unique_lock<mutex>mylock (mymutex1);
chrono::microseconds d(2000);
this_thread::sleep_for(d);
if (!msgqueue.empty())
{
command = msgqueue.front();
msgqueue.pop_front();
return true;
}
return false;
}
void MsgDequeue()
{
int command = 0;
for (int i = 0; i < 10000; ++i)
{
bool result = helper(command);
if (result)
{
cout << "helper执行,取出一个元素 " << command << endl;
}
else
{
cout << "MsgEnqueue()执行,但队列为空 " << i <<endl;
}
}
}
};
int main()
{
A a;
thread t1(&A::MsgEnqueue, &a);
thread t2(&A::MsgDequeue, &a);
t1.join();
t2.join();
cout << endl;
}
defer_lock()
使用defer_lock(),前提是先不能lock().
使用defer_lock()可以不给mutex加锁,相当于初始化了一个没有加锁的mutex
使用方法:
class A
{
private:
list<int>msgqueue;
mutex mymutex1;
public:
void MsgEnqueue()
{
for (int i = 0; i < 10000; ++i)
{
cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
unique_lock<mutex>l(mymutex1,std::defer_lock);
l.lock();//不需要自己unlock
msgqueue.push_back(i);
}
return;
}
bool helper(int & command)
{
unique_lock<mutex>mylock (mymutex1);
//chrono::microseconds d(2000);
//this_thread::sleep_for(d);
if (!msgqueue.empty())
{
command = msgqueue.front();
msgqueue.pop_front();
return true;
}
return false;
}
void MsgDequeue()
{
int command = 0;
for (int i = 0; i < 10000; ++i)
{
bool result = helper(command);
if (result)
{
cout << "helper执行,取出一个元素 " << command << endl;
}
else
{
cout << "MsgEnqueue()执行,但队列为空 " << i <<endl;
}
}
}
};
int main()
{
A a;
thread t1(&A::MsgEnqueue, &a);
thread t2(&A::MsgDequeue, &a);
t1.join();
t2.join();
cout << endl;
}
也可以提前unlock
解锁,处理一些非共享数据,如果想上锁了,可以再次lock().
比如:
for (int i = 0; i < 10000; ++i)
{
cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
unique_lock<mutex>l(mymutex1,std::defer_lock);
l.lock();//不需要自己unlock
l.unlock();
//...
//.处理非共享数据
l.lock();
msgqueue.push_back(i);
}
return;
}
try_lock()
尝试给锁上锁,如果上锁失败,返回false,否则返回true
使用方法:
cout << "MsgEnqueue()执行,插入一个元素 " << i << endl;
unique_lock<mutex>l(mymutex1,std::defer_lock);
if (l.try_lock() == true)
msgqueue.push_back(i);
else
cout << "没拿到锁 " << i << endl;
release()
返回它管理的mutex对象指针,并释放所有权.
如果你release之前,已经加锁了,release之后你要负责unlock
().
如果忘记unlock
就会报错.
注意:unique_lock
只能转移不能复制,比如:
可以看到复制构造函数已经是被禁用了,但是你可以使用移动语义来进行转移: