熱線電話:0755-23712116
郵箱:contact@shuangyi-tech.com
地址:深圳市寶安區(qū)沙井街道后亭茅洲山工業(yè)園工業(yè)大廈全至科技創(chuàng)新園科創(chuàng)大廈2層2A
如果熟悉C++多線程的童鞋可能有了解到實(shí)現(xiàn)的互斥鎖的機(jī)制還有這個(gè)寫(xiě)法
lock_guard<mutex> guard(mt);
那么這句話是什么意思呢?為什么又要搞個(gè)這樣的寫(xiě)法呢?
這個(gè)也是構(gòu)造互斥鎖的寫(xiě)法,就是會(huì)在lock_guard構(gòu)造函數(shù)里加鎖,在析構(gòu)函數(shù)里解鎖,之所以搞了這個(gè)寫(xiě)法,C++委員會(huì)的解釋是防止使用mutex加鎖解鎖的時(shí)候,忘記解鎖unlock了。
#include <iostream>
#include <thread>
#include <string>
#include <mutex>
using namespace std;
mutex mt;
void thread_task()
{
for (int i = 0; i < 10; i++)
{
lock_guard<mutex> guard(mt);
cout << "print thread: " << i << endl;
}
}
int main()
{
thread t(thread_task);
for (int i = 0; i > -10; i--)
{
lock_guard<mutex> guard(mt);
cout << "print main: " << i << endl;
}
t.join();
return 0;
}
這里說(shuō)析構(gòu)函數(shù)里解鎖,那么到底什么時(shí)候調(diào)用析構(gòu)函數(shù)呢?構(gòu)造函數(shù)加鎖我們好理解,寫(xiě)下這個(gè)語(yǔ)句的時(shí)候調(diào)用lock_guard<mutex> guard(mt),那么調(diào)用析構(gòu)函數(shù)應(yīng)該是大括號(hào){}結(jié)束的時(shí)候,也就是說(shuō)定義lock_guard的時(shí)候調(diào)用構(gòu)造函數(shù)加鎖,大括號(hào)解鎖的時(shí)候調(diào)用析構(gòu)函數(shù)解鎖。
雖然lock_guard挺好用的,但是有個(gè)很大的缺陷,在定義lock_guard的地方會(huì)調(diào)用構(gòu)造函數(shù)加鎖,在離開(kāi)定義域的話lock_guard就會(huì)被銷(xiāo)毀,調(diào)用析構(gòu)函數(shù)解鎖。這就產(chǎn)生了一個(gè)問(wèn)題,如果這個(gè)定義域范圍很大的話,那么鎖的粒度就很大,很大程序上會(huì)影響效率。
所以為了解決lock_guard鎖的粒度過(guò)大的原因,unique_lock就出現(xiàn)了。
unique_lock<mutex> unique(mt);
這個(gè)會(huì)在構(gòu)造函數(shù)加鎖,然后可以利用unique.unlock()來(lái)解鎖,所以當(dāng)你覺(jué)得鎖的粒度太多的時(shí)候,可以利用這個(gè)來(lái)解鎖,而析構(gòu)的時(shí)候會(huì)判斷當(dāng)前鎖的狀態(tài)來(lái)決定是否解鎖,如果當(dāng)前狀態(tài)已經(jīng)是解鎖狀態(tài)了,那么就不會(huì)再次解鎖,而如果當(dāng)前狀態(tài)是加鎖狀態(tài),就會(huì)自動(dòng)調(diào)用unique.unlock()來(lái)解鎖。而lock_guard在析構(gòu)的時(shí)候一定會(huì)解鎖,也沒(méi)有中途解鎖的功能。
當(dāng)然,方便肯定是有代價(jià)的,unique_lock內(nèi)部會(huì)維護(hù)一個(gè)鎖的狀態(tài),所以在效率上肯定會(huì)比lock_guard慢。
所以,以上兩種加鎖解鎖的方法,加上前面文章介紹的mutex方法,具體該使用哪一個(gè),要依照具體的業(yè)務(wù)需求來(lái)決定,當(dāng)然mt.lock()和mt.unlock()不管是哪種情況,是肯定都可以使用的。
對(duì)我而言,總感覺(jué)這個(gè)lock_guard有點(diǎn)雞肋而已,完全可以用mutex來(lái)替代,忘記解鎖的話一般都可以通過(guò)調(diào)試發(fā)現(xiàn),而且一般情況下都不會(huì)忘記。僅僅只是因?yàn)榕峦浗怄i這個(gè)原因的話,真的感覺(jué)有點(diǎn)多此一舉,徒增學(xué)習(xí)成本罷了。
當(dāng)然也許C++委員會(huì)有他們自己的考慮,對(duì)于我們而言,也只能記住就是了。