您好,登錄后才能下訂單哦!
本篇內容介紹了“C++中mutex和lock的用法”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
mutex用來協助采取獨占方式控制對資源的并發訪問,這里的資源可能是一個對象,或多個對象的組合,為了獲得獨占式的資源訪問能力,相應的線程必須鎖定mutex,這樣可以防止其它線程也鎖定該mutex。
下面兩條線程如果沒有使用mutex來同步,則輸出結果會是112233。
mutex g_mutex;
void print123()
{
g_mutex.lock();
for (int i = 0; i < 3; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << i + 1;
}
g_mutex.unlock();
}
int main()
{
thread(print123).detach();
thread(print123).detach();//123123
system("pause");
}
你應該確保mutex對象調用lock后,即使發生異常也會調用unlock,否則有可能造成資源被永遠鎖住或者死鎖。
為此我們可以使用lock_guard來進行lock和unlock,lock_guard在構造時會lock,析構時會unlock,使用大括號對可以加快lock_guard的析構,需要注意的是lock_guard一定要分配變量名,否則不會有效果。
void print123()
{
lock_guard<mutex> lockGuard(g_mutex);
for (int i = 0; i < 3; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << i + 1;
}
}
同一線程多次鎖定mutex會導致程序終止,而recursive_mutex則不會,這個mutex允許同一線程多次鎖定。
recursive_mutex g_mutex;
void print123()
{
g_mutex.lock();
g_mutex.lock();
for (int i = 0; i < 3; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << i + 1;
}
g_mutex.unlock();
g_mutex.unlock();
}
有時候線程想要鎖定mutex,但又不想其它線程已鎖定mutex時阻塞,這種情況下可以使用try_lock,它試圖鎖定mutex,成功就返回true,失敗返回false。
為了等待特定長度的時間,你可以使用timed_mutex或recursive_timed_mutex的try_lock_for或try_lock_until方法。
由于try_lock在返回true時會鎖定mutex,為了防止lock_guard重復鎖定,需要傳遞參數adopt_lock。
void print123()
{
if (g_mutex.try_lock()) {
lock_guard<mutex> lockGuard(g_mutex,adopt_lock);
for (int i = 0; i < 3; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << i + 1;
}
} else {
cout << "mutex locked" <<endl;
}
}
int main()
{
thread(print123).detach();
thread(print123).detach();
system("pause");
}
通常一個線程一次只鎖定一個mutex,然而有時候必須鎖定多個mutex,如果一個個鎖定,有可能出現鎖定了第一個mutex,而無法鎖定第二個mutex的情況。這種情況下可以使用全局函數lock鎖定多個mutex。
mutex g_mutex1;
mutex g_mutex2;
void print123()
{
lock(g_mutex1, g_mutex2);
lock_guard<mutex> lockGuard1(g_mutex1, adopt_lock);
lock_guard<mutex> lockGuard2(g_mutex2, adopt_lock);
for (int i = 0; i < 3; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << i + 1;
}
}
int main()
{
thread(print123).detach();
thread(print123).detach();
system("pause");
}
使用全局函數try_lock嘗試鎖定多個mutex,如果鎖定所有mutex則返回-1,否則返回第一個失敗的mutex的索引(從0開始),并且所有被成功lock的mutex會又被unlock。
mutex g_mutex1;
mutex g_mutex2;
void print123()
{
lock(g_mutex1, g_mutex2);
lock_guard<mutex> lockGuard1(g_mutex1, adopt_lock);
lock_guard<mutex> lockGuard2(g_mutex2, adopt_lock);
for (int i = 0; i < 3; i++) {
this_thread::sleep_for(chrono::milliseconds(100));
cout << i + 1;
}
}
void printLockState()
{
auto result = try_lock(g_mutex1, g_mutex2);
cout << result << endl;
if (result == -1) {
lock_guard<mutex> lockGuard1(g_mutex1, adopt_lock);
lock_guard<mutex> lockGuard2(g_mutex2, adopt_lock);
}
}
int main()
{
thread(print123).detach();
thread(printLockState).detach();
system("pause");
}
除了lock_guard,C++還提供一個類似的類unique_lock,它比lock_guard更靈活,unique_lock允許你明確指定何時鎖定或解鎖mutex,而lock_guard總是鎖定mutex,如果unique_lock析構時mutex仍被鎖住,析構函數會自動調用unlock,如果沒有則不做任何事。
mutex g_mutex1;
timed_mutex g_mutex2;
int main()
{
//嘗試鎖定mutex,但不會阻塞
unique_lock<mutex> uniqueLock1(g_mutex1, try_to_lock);
//嘗試鎖定mutex,不超過10秒
unique_lock<timed_mutex> uniqueLock2(g_mutex2, chrono::seconds(10));
//主動調用lock,try_lock,try_lock_for等才會鎖定
unique_lock<mutex> uniqueLock3(g_mutex1, defer_lock);
//通過已鎖定的mutex初始化
unique_lock<mutex> uniqueLock4(g_mutex1, adopt_lock);
//判斷有沒有鎖定mutex
cout << (uniqueLock1 ? "locked" : "unlocked")<< endl;
cout << uniqueLock1.owns_lock() << endl;
//解鎖mutex
uniqueLock1.unlock();
//鎖定mutex
uniqueLock3.lock();
system("pause");
}
“C++中mutex和lock的用法”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。