熱線電(dian)話(hua):0755-23712116
郵箱:contact@legoupos.cn
地址:深圳市寶安區沙井街道后亭茅洲山工業(ye)園(yuan)工業(ye)大廈(sha)全至(zhi)科(ke)技創新園(yuan)科(ke)創大廈(sha)2層2A
如(ru)果熟悉(xi)C++多線(xian)程的(de)(de)童鞋可能有了解到(dao)實現的(de)(de)互斥鎖的(de)(de)機制還有這個寫法(fa)
lock_guard<mutex> guard(mt);
那么這句話是(shi)什么意思(si)呢?為什么又(you)要(yao)搞個這樣的寫(xie)法呢?
這個也是(shi)構造(zao)(zao)互(hu)斥鎖的寫法,就是(shi)會(hui)在(zai)lock_guard構造(zao)(zao)函數里(li)加鎖,在(zai)析(xi)構函數里(li)解鎖,之所以(yi)搞了這個寫法,C++委(wei)員(yuan)會(hui)的解釋(shi)是(shi)防止使用mutex加鎖解鎖的時候,忘記(ji)解鎖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;
}
這(zhe)(zhe)里(li)說析(xi)構(gou)函(han)數(shu)(shu)(shu)里(li)解鎖(suo),那么(me)到底(di)什么(me)時(shi)候(hou)調(diao)用析(xi)構(gou)函(han)數(shu)(shu)(shu)呢?構(gou)造函(han)數(shu)(shu)(shu)加(jia)鎖(suo)我們好理解,寫下(xia)這(zhe)(zhe)個語句的(de)時(shi)候(hou)調(diao)用lock_guard<mutex> guard(mt),那么(me)調(diao)用析(xi)構(gou)函(han)數(shu)(shu)(shu)應該是大括號{}結(jie)束的(de)時(shi)候(hou),也就是說定義lock_guard的(de)時(shi)候(hou)調(diao)用構(gou)造函(han)數(shu)(shu)(shu)加(jia)鎖(suo),大括號解鎖(suo)的(de)時(shi)候(hou)調(diao)用析(xi)構(gou)函(han)數(shu)(shu)(shu)解鎖(suo)。
雖(sui)然(ran)lock_guard挺好用(yong)的(de)(de),但是有個很大的(de)(de)缺(que)陷,在定(ding)義lock_guard的(de)(de)地方會調用(yong)構(gou)造函數加鎖,在離開定(ding)義域(yu)的(de)(de)話(hua)lock_guard就(jiu)會被(bei)銷毀,調用(yong)析構(gou)函數解鎖。這(zhe)就(jiu)產生了一個問題,如果這(zhe)個定(ding)義域(yu)范圍很大的(de)(de)話(hua),那么鎖的(de)(de)粒度就(jiu)很大,很大程(cheng)序(xu)上會影響(xiang)效率。
所以為了(le)解決(jue)lock_guard鎖的粒(li)度過大的原(yuan)因,unique_lock就(jiu)出現了(le)。
unique_lock<mutex> unique(mt);
這個會(hui)(hui)在(zai)構造函數加鎖(suo)(suo)(suo),然后(hou)可(ke)(ke)以(yi)利用(yong)unique.unlock()來(lai)(lai)解(jie)(jie)鎖(suo)(suo)(suo),所以(yi)當(dang)(dang)(dang)你(ni)覺得鎖(suo)(suo)(suo)的(de)(de)粒度太多的(de)(de)時候(hou),可(ke)(ke)以(yi)利用(yong)這個來(lai)(lai)解(jie)(jie)鎖(suo)(suo)(suo),而(er)析(xi)構的(de)(de)時候(hou)會(hui)(hui)判斷(duan)當(dang)(dang)(dang)前(qian)(qian)鎖(suo)(suo)(suo)的(de)(de)狀態(tai)來(lai)(lai)決(jue)定是(shi)否(fou)解(jie)(jie)鎖(suo)(suo)(suo),如(ru)果當(dang)(dang)(dang)前(qian)(qian)狀態(tai)已(yi)經(jing)是(shi)解(jie)(jie)鎖(suo)(suo)(suo)狀態(tai)了,那(nei)么就(jiu)不會(hui)(hui)再(zai)次解(jie)(jie)鎖(suo)(suo)(suo),而(er)如(ru)果當(dang)(dang)(dang)前(qian)(qian)狀態(tai)是(shi)加鎖(suo)(suo)(suo)狀態(tai),就(jiu)會(hui)(hui)自動調用(yong)unique.unlock()來(lai)(lai)解(jie)(jie)鎖(suo)(suo)(suo)。而(er)lock_guard在(zai)析(xi)構的(de)(de)時候(hou)一定會(hui)(hui)解(jie)(jie)鎖(suo)(suo)(suo),也沒有中途(tu)解(jie)(jie)鎖(suo)(suo)(suo)的(de)(de)功能。
當然,方便肯定(ding)是有代價(jia)的,unique_lock內部會(hui)(hui)維護一(yi)個(ge)鎖的狀態,所以在效率上肯定(ding)會(hui)(hui)比(bi)lock_guard慢。
所以(yi),以(yi)上(shang)兩種(zhong)加鎖解鎖的(de)方法(fa),加上(shang)前面文章介紹的(de)mutex方法(fa),具(ju)體(ti)該(gai)使用哪(na)一個,要依照具(ju)體(ti)的(de)業務需求來決(jue)定,當然mt.lock()和(he)mt.unlock()不管是哪(na)種(zhong)情(qing)況,是肯定都可以(yi)使用的(de)。
對(dui)我而言,總(zong)感(gan)覺這(zhe)個lock_guard有點(dian)雞肋而已,完全(quan)可(ke)以(yi)用mutex來替代,忘(wang)記解(jie)鎖的(de)(de)話一(yi)般都(dou)可(ke)以(yi)通(tong)過(guo)調試發現,而且(qie)一(yi)般情況下都(dou)不會忘(wang)記。僅僅只(zhi)是(shi)因為怕忘(wang)記解(jie)鎖這(zhe)個原(yuan)因的(de)(de)話,真的(de)(de)感(gan)覺有點(dian)多(duo)此(ci)一(yi)舉,徒增學習成本罷(ba)了(le)。
當然也許(xu)C++委(wei)員會有他們自(zi)己的考慮,對于我們而言,也只能記(ji)住就是了。