C++11多線程編程(二)——互斥鎖mutex用法

2021-02-26 一點月光
還是那個問題,編程世界中學習一個新的技術點,一定要明白一件事,為什麼要出現這個技術點,只有弄懂了這個才能從根本上有學習的動力。那麼為什麼要出現多線程鎖這個東西呢?一句話概括的話。

計算機就是為了計算數據才誕生的,如果不能保證數據準確的話,任何技術都只是空中樓閣,多線程技術也是一樣,那麼為什麼多線程會讓數據不準確呢?大家可以看下以下的這個例子

#include <iostream>
#include <thread>
#include <string>
using namespace std;

void thread_task()
{
for (int i = 0; i < 10; i++)
{
cout << "print thread: " << i << endl;
}
}
int main()
{
thread t(thread_task);
for (int i = 0; i > -10; i--)
{
cout << "print main: " << i << endl;
}
t.join();
return 0;

}

大家可以看到產生了一個很奇怪的現象,按理說輸出「print thread:」之後應該跟著i的值,但是i的值卻跑到「print main:」的後面了,這顯然不是我們能要的結果,那為什麼會這樣呢?因為多線程執行的話,是作業系統內部控制的,一般是通過時間片輪詢來輪流執行的,甚至在多核CPU下是並行執行的。那麼怎麼解決這個問題呢?以便我們在一個線程裡處理完我們所需要的數據之後,然後才將控制權交出呢?這個就是用到鎖這個東西。假設線程A在執行cout << "print thread: " << i << endl;這個代碼之前,在前面鎖住一下,當線程B想來搶奪控制權的時候,發現這個地方已經被上鎖了,無法搶奪,只能等待,等待它釋放。執行完那個代碼之後就可以釋放鎖,然後B線程就是來搶奪控制權了,一旦B獲得了控制權也給自己上了鎖,防止在執行關鍵地方的時候被別人奪去控制權。那麼C++如何實現加鎖的過程的呢?C++當中用到的一個類是mutex,這個中文就是互斥量的意思,顧名思義,就是一個時刻只能有一個訪問,以下是代碼

#include <iostream>
#include <thread>
#include <string>
#include <mutex>
using namespace std;

mutex mt;
void thread_task()
{
for (int i = 0; i < 10; i++)
{
mt.lock();
cout << "print thread: " << i << endl;
mt.unlock();
}
}

int main()
{
thread t(thread_task);
for (int i = 0; i > -10; i--)
{
mt.lock();
cout << "print main: " << i << endl;
mt.unlock();
}
t.join();
return 0;
}

在需要加鎖的地方,調用metex的lock()方法,解鎖的地方unloc()方法,這樣就可以順序的輸出了所需要的結果了。

以上就是C++中關於互斥鎖的機制,相當的簡單容易理解。

更多精彩內容,請關注同名公眾:一點筆記alittle

相關焦點

  • UNIX(多線程):04---Mutex互斥量
    如果你要在代碼裡使用和互斥量相關的變量或者函數,你需要包含頭文件mutex,std::mutex 是 C++11 中最基本的互斥量,std::mutex 對象提供了獨佔所有權的特性——即不支持遞歸地對 std::mutex 對象上鎖,而 std::recursive_lock 則可以遞歸地對互斥量對象上鎖。
  • c++11新特性之線程相關所有知識點
    ,這裡按照如下順序介紹:std::thread相關c++11之前你可能使用pthread_xxx來創建線程,繁瑣且不易讀,c++11引入了std::thread來創建線程,支持對線程join或者detach。
  • C語言邊角料2:用純軟體來代替Mutex互斥鎖
    一、前言二、Peterson 算法簡介三、測試代碼四、Mutex 互斥鎖對代碼執行效率的影響五、總結一、前言 在 Linux 系統中,當多個線程並行執行時我們知道,一個臨界區必須保證 3 個條件:互斥訪問: 在任意一個時刻,最多只能有一個線程可以進入臨界區;空閒讓進:當沒有線程正在執行臨界區的代碼時,必須在所有申請進入臨界區的線程中,選擇其中的一個,讓它進入臨界區;有限等待:當一個線程申請進去臨界區時,不能無限的等待,必須在有限的時間內獲得許可進入臨界區。也就是說,不論其優先級多低,不應該餓死在該臨界區入口處。
  • C++ mutex詳解
    一、mutex頭文件的介紹Mutex 又稱互斥量,C++ 11中與 Mutex 相關的類(包括鎖類型)和函數都聲明在 < mutex > 頭文件中,所以如果你需要使用 std::mutex,就必須包含 < mutex > 頭文件。
  • 自旋鎖和互斥鎖區別
    POSIX threads(簡稱Pthreads)是在多核平臺上進行並行編程的一套常用的API。
  • 關於條件變量與互斥鎖、信號量的區別,Linux下線程同步的幾種方法
    mutex互斥鎖必須是普通鎖(PTHREAD_MUTEX_TIMED_NP)或者適應鎖(PTHREAD_MUTEX_ADAPTIVE_NP),且在調用pthread_cond_wait()前必須由本線程加鎖(pthread_mutex_lock()),而在更新條件等待隊列以前,mutex保持鎖定狀態,並在線程掛起進入等待前解鎖。
  • python(21):python中的多線程和互斥鎖
    __init__(self)然後我們需要重寫主方法,run方法,最後用start調用import timefrom threading import Threadclass Test(Thread): def __init__(self): super()._
  • C#多線程學習lock,Monitor,Mutex的區別
    二、Monitor有TryEnter的功能,可以防止出現死鎖的問題,lock沒有。Mutex和其他兩者的區別個人測試三個都是在限制線程之外的互斥,線程之內,都不限制,同一個線程如果被lock兩次。是不會出現死鎖的。所以Mutex本身可以實現lock和Monitor所有的操作。至少從功能上講是這樣的。
  • Linux C 多線程編程之互斥鎖與條件變量實例詳解
    //多線程同步--條件鎖(相當與windows的事件)測試//要先讓pthread_cond_wait進入等待信號狀態,才能調用pthread_cond_signal發送信號,才有效.//不能讓pthread_cond_signal在pthread_cond_wait前面執行#include <stdio.h>#include<pthread.h> //多線程所用頭文件#include <semaphore.h> //信號量使用頭文件pthread_cond_t g_cond
  • 使用Mutex進行線程處理
    關鍵部分是訪問共享資源(數據結構或設備)的一段代碼,但條件是一次只能有一個線程進入此部分。現代程式語言天生就支持這一點。。在C#中,像下面這樣簡單:使用Mutex類,您可以調用WaitHandle.WaitOne方法加鎖,用ReleaseMutex釋放這個鎖。關閉或dispose Mutex會自動釋放它。
  • 【Linux公開課】加鎖與解鎖(互斥量)
    加鎖 線程試圖鎖定互斥量的過程稱之為加鎖。 Pthreads中有兩個試圖鎖定互斥量的函數,pthread_mutex_lock()和pthread_mutex_trylock()。pthread_mutex_lock()函數會一直阻塞到互斥量可用為止,而pthread_mutex_trylock()會嘗試加鎖,通常立即返回。
  • 如何理解互斥鎖、條件變量、讀寫鎖以及自旋鎖?
    恰好pthread包含這幾種鎖的API,而C++11隻包含其中的部分。接下來我主要通過pthread的API來展開本文。mutex(互斥量)mutex(mutual exclusive)即互斥量(互斥體)。也便是常說的互斥鎖。儘管名稱不含lock,但是稱之為鎖,也是沒有太大問題的。mutex無疑是最常見的多線程同步方式。
  • 兩個線程,兩個互斥鎖,怎麼形成一個死循環?
    ,兩個互斥鎖如何形成死鎖?程序流程圖如下:程序流程圖如上圖所示:t0時刻,主線程創建子線程,並初始化互斥鎖mutex1、mutex2;t1時刻,主線程申請到了mutex1、子線程申請到了mutex2;t2時刻,主線程和子線程都sleep 1秒鐘,防止優先獲得時間片的線程直接申請到了另外1個互斥鎖,導致程序直接退出
  • 多線程安全——鎖
    競爭條件兩個或多個線程讀寫某些共享數據,而最後的結果取決於線程運行的精確時序,稱為競爭條件(race conditon)2.在某一個時刻,L處於臨界區中,此時H變為就緒態,線程切換,L被切換出變為就緒態,H運行線程忙等待,但是由於L不會被調度,也就無法離開臨界區,所以H將永遠忙等待下去。這種情況有時被稱作優先級反轉問題(priority inversion problem)。解決忙等待問題需要引入通信原語,它們在無法進入臨界區時將阻塞,而不是忙等待。
  • C++11多線程編程(三)——lock_guard和unique_lock
    如果熟悉C++多線程的童鞋可能有了解到實現的互斥鎖的機制還有這個寫法lock_guard<
  • C++ 線程局部變量thread_local
    (一)在Linux系統中使用C/C++進行多線程編程時,我們遇到最多的就是對同一變量的多線程讀寫問題,大多情況下遇到這類問題都是通過鎖機制來處理,但這對程序的性能帶來了很大的影響,當然對於那些系統原生支持原子操作的數據類型來說,我們可以使用原子操作來處理,這能對程序的性能會得到一定的提高。
  • 詳解 C++ 多線程的condition_variable
    std::condition_variable對象通常使用std::unique_lock<std::mutex>來等待,如果需要使用另外的lockable類型,可以使用 std::condition_variable_any 類,本文後面會講到 std::condition_variable_any 的用法。
  • 淺談互斥鎖與進程間的通信 (舉例說明)
    一、互斥鎖
  • 原子操作和互斥鎖的區別
    這個系列的文章裡介紹了很多並發編程裡經常用到的技術,除了Context、計時器、互斥鎖還有通道外還有一種技術
  • C語言進階27-多線程處理過程的交叉運行
    也就是說可能一個線程在運行第10行指令的同時另一個線程在運行第12行的指令. 成百上千個不同程序在不同時間的運行時產生的微秒級差異造就了不可以根據一般方法來預測給定的線程在給定時間運行的內容.02線程同步   上面介紹了多線程編程問題. 問題出現的原因在於無法預測多線程運行時的讀取和改變共享變量的值時的順序.