繼續記錄鎖的一些概念,眼瞅著疫情的拐點即將出現了。
unique_lock
unique_lock這個是可以取代前一篇寫的lock_guard,在第二個引數的為adopt_lock時與之前一樣,表示unique_lock物件已經繫結了互斥量,提前lock互斥量,不用自己去unlock了,其實不建議搞這些花裡胡哨的,lock和unlock對稱使用貌似還清楚一點。
使用方法就是直接將lock_guard換成unique_lock
#include
#include
#include
#include
using
namespace std;
classa}
void
outcommand()
else}}
private
: list<
int> ticket;
mutex mylock1;
mutex mylock2;};
intmain
(int argc,
char
*ar**)
完全替換那要他有何用,存在即合理,設想一下,執行緒一拿到鎖後要執行好長一段時間,執行緒二在等這個鎖,難道他就這麼一直等下去麼,所以unique_lock的作用就體現出來,
try_to_lock引數,表示嘗試去鎖,如果沒有鎖定成功那麼就可以去執行別的程式,並不會一直處於等待狀態。
**的寫法如圖所示:
unique_lock
myunique
(mymutex, try_to_lock);if
(myunique.
own_lock()
)else
defer_lock引數,這個引數就是表示初始化了乙個沒有加鎖的mutex,需要自己加鎖,互斥量的解鎖,到生命週期結束後自動結束。或者自己中途解鎖也行。
2 成員函式release();
返回指向mutex指標,並解除物件與mutex的繫結,並通過指標進行呼叫解鎖函式。
使用方法如圖所示:
unique_lock
myunique
(mymutex, try_to_lock)
;//定義乙個該型別指標
mutex *ptx = myunique.
release()
;ticket.
push_back
(i);
ptx-
>
unlock()
;
或者通過移動語義move換個物件繫結
例如:
unique_lock
myunique
(mymutex)
;unique_lock
myunique2
(move
(myunique));
//定義乙個指標
mutex *ptx = myunique2.
release()
;ticket.
push_back
(i);
ptx-
>
unlock()
;
3.鎖的粒度這個是乙個概念,鎖住的**少,那麼鎖的粒度就細,執行效率就越高
鎖住的**多,那麼鎖的粒度就粗,執行效率就越低,根據情況選擇適合的粒度,當然了,這概念我也只是聽到,沒有實際的體驗,先記下再說。
單例模式
這裡順便記錄一下單例模式,之前一直模模糊糊不太懂,面試基本這個問題回答不上來。
單例模式:在整個任務中,有一些特殊的類,在程式裡只能建立乙個物件,
先放上**:
```cpp
#include
using
namespace std;
class
myclass
;private
:static myclass *myptr;
public
:static myclass *
getinstance()
return myptr;
}void
myprint()
};myclass *myclass::myptr =
null
;int
main
(int ar**,
char
*argc)
執行結果如圖所示:
建構函式的私有化,防止新建多個物件,指標所指向的物件唯一,並且靜態表示不屬於任何乙個物件,屬於類。此時**的myptr1和myptr2所指向的位址是乙個位址。
但這裡你會發現兩個問題,
一:new和delete是成對出現的,這個程式就不完美。
二:如果是兩個執行緒進行new 物件,那麼會出現執行緒一未完成new物件,進行到一半,而時間片轉到執行緒二時,此時他又可以new乙個,因為執行緒一未完全結束new物件,這樣的話程式就可以產生兩個new物件了,不符合單例模式的要求,因此借鑑案例分別引入
類中類,建立物件,然後推出程式的時候自動執行析構函式,函式中新增delete指標和互斥量的方法,執行緒進行加鎖的方式進行互斥訪問。
方法如圖所示:
#include
#include
#include
using
namespace std;
mutex mymutex;
class
myclass
;private
:static myclass *myptr;
public
:static myclass *
getinstance()
}return myptr;
}class
delclass}}
;void
myprint()
};myclass *myclass::myptr =
null
;void
myfunc()
intmain
(int ar**,
char
*argc)
執行結果顯示,正確無異常,且在程式退出後顯示delete指標。
後來了解到,c++11提供了乙個函式call_once();可以代替這個只執行一次的new物件這個操作,以及增加引數互斥標誌,就是全給你搞好了。
#include
#include
#include
using
namespace std;
mutex mymutex;
once_flag myflag;
class
myclass
;private
:static myclass *myptr;
public
:static
void
singlecreate()
static myclass *
getinstance()
// }
return myptr;
}class
delclass};
void
myprint()
};myclass *myclass::myptr =
null
;void
myfunc()
intmain
(int ar**,
char
*argc)
可以看到,結果與上述**一樣,可以單換。
留乙個問題算了,getinstance為啥是指標返回,不是引用返回和值返回
C 11的多執行緒併發程式設計(五)
疫情確診人數連續12天下降,終將結束,然鵝還是處於不能出門狀態,繼續記筆記吧。條件變數 condition variable 假設有兩個執行緒就是前篇記錄的放佇列資料線程,和讀佇列資料線程,條件變數就是乙個條件類,等待乙個條件達成即執行 執行成員函式wait 等待另乙個執行緒執行notify one...
C 11併發程式設計 多執行緒std thread
c 11引入了thread類,大大降低了多執行緒使用的複雜度,原先使用多執行緒只能用系統的api,無法解決跨平台問題,一套 平台移植,對應多執行緒 也必須要修改。現在在c 11中只需使用語言層面的thread可以解決這個問題。所需標頭檔案 thread noexcept 乙個空的std thread...
C 11 多執行緒 併發程式設計總結
建立std thread,一般會繫結乙個底層的執行緒。若該thread還繫結好函式物件,則即刻將該函式執行於thread的底層執行緒。執行緒相關的很多預設是move語義,因為在常識中線程複製是很奇怪的行為。joinable 是否可以阻塞至該thread繫結的底層執行緒執行完畢 倘若該thread沒有...