頭文件<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
只能轉移不能複製,比如:
可以看到複製構造函數已經是被禁用了,但是你可以使用移動語義來進行轉移: