• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 多線程控制互斥鎖與信號量

    標簽: 多線程控制互斥鎖與信號量

    1.多線程編臨界資源訪問

    #define _GNU_SOURCE 
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    int Num = 0;
    void *fun1(void *arg)
    {
            while(Num<3){
                    Num++;
                    printf("%s :Num = %d\n",__FUNCTION__,Num);
                    sleep(1);
            }
            pthread_exit(NULL);
    }
    void *fun2(void *arg)
    {
            while(Num>-3){
                    Num--;
                    printf("%s :Num = %d\n",__FUNCTION__,Num);
                    sleep(1);
            }
            pthread_exit(NULL);
    }
    int main()
    {
            int ret;
            pthread_t tid1,tid2;
            ret = pthread_create(&tid1,NULL,fun1,NULL);
            if(ret != 0){
                    perror("pthread_creat");
                    return -1;
            }
            ret = pthread_create(&tid2,NULL,fun2,NULL);
            if(ret != 0){
                    perror("pthread_creat");
                    return -1;
            }
            pthread_join(tid1,NULL);
            pthread_join(tid2,NULL);
            return 0;
    		
    }
    
    

    為了解決上述對臨界資源的競爭問題,pthread線程引出了互斥鎖來解決臨界資源訪問。通過對臨界資源加鎖來保護資源只被單個線程操作,待操作結束后解鎖,其余線程才可獲得操作權。
    2.互斥鎖API簡述
    在這里插入圖片描述
    函數作用為初始化一個互斥鎖,一般情況申請一個全局的pthread_mutex_t類型的互斥鎖變量,通過此函數完成鎖內的初始化,第一個函數將該變量的地址傳入,第二個參數為控制互斥鎖的屬性,一般為NULL。當函數成功后會返回0,代表初始化互斥鎖成功。當然初始化互斥鎖也可以調用宏來快速初始化:
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITALIZER;
    在這里插入圖片描述
    lock函數與unlock函數分別為加鎖解鎖函數,只需要傳入已經初始化好的pthread_mutex_t互斥鎖變量,成功后會返回0。當某一個線程獲得了執行權后,執行lock函數,一旦加鎖成功后,其余線程遇到lock函數時候會發生阻塞,直至獲取資源的線程執行unlock函數后,獲得第二執行權的線程的阻塞模式被從開,同時也獲取了lock,導致其余線程同樣在阻塞,直至執行unlock被解鎖
    特別注意的是,當獲取lock之后,必須在邏輯處理結束后執行unlock,否則會發生死鎖現象!導致其余線程一直處于阻塞狀態,無法執行下去。在使用互斥鎖的時候,尤其要注意使用pthread_cancel函數,防止發生死鎖現象!
    在這里插入圖片描述
    該函數同樣也是一個線程加鎖函數,但該函數是非阻塞模式通過返回值來判斷是否加鎖成功,用法與上述阻塞加速函數一致
    在這里插入圖片描述
    該函數是用于銷毀互斥鎖的,傳入互斥鎖的地址,就可以完成互斥鎖的銷毀,成功返回0

    #define _GNU_SOURCE 
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    pthread_mutex_t mutex;
    int Num = 0;
    void *fun1(void *arg)
    {
            pthread_mutex_lock(&mutex);
            while(Num<3){
                    Num++;
                    printf("%s :Num = %d\n",__FUNCTION__,Num);
                    sleep(1);
            }
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
    }
    void *fun2(void *arg)
    {
            pthread_mutex_lock(&mutex);
            while(Num>-3){
                    Num--;
                    printf("%s :Num = %d\n",__FUNCTION__,Num);
                    sleep(1);
            }
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
    }
    int main()
    {
            int ret;
            pthread_t tid1,tid2;
            ret = pthread_mutex_init(&mutex,NULL);
            if(ret != 0){
                    perror("pthread_mutex_init");
                    return 0;
            }
            ret = pthread_create(&tid1,NULL,fun1,NULL);
            if(ret != 0){
                    perror("pthread_creat");
                    return -1;
            }
            ret = pthread_create(&tid2,NULL,fun2,NULL);
            if(ret != 0){
                    perror("pthread_creat");
                    return -1;
            }
            pthread_join(tid1,NULL);
            pthread_join(tid2,NULL);
            pthread_mutex_destroy(&mutex);
            return 0;
    
    }
    
    

    上述例程通過加入互斥鎖,保證了臨界變量某一時刻只被某一線程控制,實現了臨界資源的控制。
    在這里插入圖片描述
    3.多線程編執行順序控制 信號量API簡述
    在這里插入圖片描述
    該函數可以初始化一個信號量,第一個參數傳入sem_t類型的地址,第二個參數傳入0代表線程控制,否則為進程控制,第三個參數表示信號量的初始值,0代表阻塞,1代表運行。待初始化結束信號量后,若執行成功會返回0。
    在這里插入圖片描述
    sem_wait函數作用為檢測指定信號量是否有資源可用,若無資源可用會阻塞等待,若有資源可用會自動的執行“sem-1”的操作。所謂的“sem-1”是與上述初始化函數中第三個參數值一致,成功執行會返回0
    sem_post函數會釋放指定信號量的資源,執行“sem+1”操作。
    通過以上2個函數可以完成所謂的PV操作,即信號量的申請與釋放,完成對線程執行順序的控制。
    在這里插入圖片描述
    與互斥鎖一樣,此函數是控制信號量申請資源的非阻塞函數,功能與sem_wait一致,唯一區別在于此函數為非阻塞
    在這里插入圖片描述
    該函數為信號量銷毀函數,執行過后可將申請的信號量進行銷毀

    #define _GNU_SOURCE 
    #include <pthread.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <semaphore.h>
    sem_t sem1,sem2,sem3;//申請的三個信號量變量
    void *fun1(void *arg)
    {
            sem_wait(&sem1);//因sem1本身有資源,所以不被阻塞 獲取后sem1-1 下次會會阻塞
            printf("%s:Pthread Come!\n",__FUNCTION__);
            sem_post(&sem2);// 使得sem2獲取到資源
            pthread_exit(NULL);
    }
    void *fun2(void *arg)
    {
            sem_wait(&sem2);//因sem2在初始化時無資源會被阻塞,直至14行代碼執行 不被阻塞 sem2-1 下次會阻塞
            printf("%s:Pthread Come!\n",__FUNCTION__);
            sem_post(&sem3);
            pthread_exit(NULL);
    }
    void *fun3(void *arg)
    {
            sem_wait(&sem3);
            printf("%s:Pthread Come!\n",__FUNCTION__);
            sem_post(&sem1);
            pthread_exit(NULL);
    }
    int main()
    {
            int ret;
            pthread_t tid1,tid2,tid3;
            ret = sem_init(&sem1,0,1);//初始化信號量1 并且賦予其資源
            if(ret < 0){
                    perror("sem_init");
                    return -1;
            }
            ret = sem_init(&sem2,0,0);//初始化信號量2 讓其阻塞
            if(ret < 0){
                    perror("sem_init");
                    return -1;
            }
            ret = sem_init(&sem3,0,0);//初始化信號3 讓其阻塞
            if(ret < 0){
                    perror("sem_init");
                    return -1;
            }
            ret = pthread_create(&tid1,NULL,fun1,NULL);
            if(ret != 0){
                    perror("pthread_create");
                    return -1;
            }
            ret = pthread_create(&tid2,NULL,fun2,NULL);
            if(ret != 0){
                    perror("pthread_create");
                    return -1;
            }
    		ret = pthread_create(&tid3,NULL,fun3,NULL);
            if(ret != 0){
                    perror("pthread_create");
                    return -1;
            }
            /*回收線程資源*/
            pthread_join(tid1,NULL);
            pthread_join(tid2,NULL);
            pthread_join(tid3,NULL);
            /*銷毀信號量*/
            sem_destroy(&sem1);
            sem_destroy(&sem2);
            sem_destroy(&sem3);
            return 0;
    
    }
    
    

    在這里插入圖片描述
    該例程加入了信號量的控制使得線程的執行順序變為可控的,在初始化信號量時,將信號量1填入資源,使之不被sem_wait函數阻塞,在執行完邏輯后使用sem_pos函數來填入即將要執行的資源。當執行函數sem_wait后,會執行sem自減操作,使下一次競爭被阻塞,直至通過sem_pos被釋放。

    版權聲明:本文為weixin_46571142原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/weixin_46571142/article/details/109720153

    智能推薦

    Linux線程-Mutex互斥鎖和信號量互斥鎖的筆記

    多線程開發在 Linux 平臺上已經有成熟的 pthread 庫支持。其涉及的多線程開發的最基本概念主要包含三點:線程,互斥鎖,條件。其中,線程操作又分線程的創建,退出,等待 3 種。互斥鎖則包括 4 種操作,分別是創建,銷毀,加鎖和解鎖。條件操作有 5 種操作:創建,銷毀,觸發,廣播和等待。其他的一些線程擴展概念,如信號燈等,都可以通過上面的三個基本元素的基本操作封裝出來。詳細請見下表: 線程創...

    線程間的同步與互斥—信號量

    線程間的同步與互斥—信號量 之前的博客有學習過關于進程間通信的信號量,那關于線程之間的同步和互斥的信號量是怎么理解的呢? 線程之間的Mutex變量是非0即1的,可以看作是一種資源的計數器,初始化時Mutex是1,表示有一個可用資源,加鎖的時候表示獲得該資源,將Mutex減1,置為0,表示此時沒有可用資源,解鎖的時候在重新釋放該資源,將Mutex重新加到1,表示此時又有了一個資源。關于信...

    Linux多線程實踐 --Posix信號量與互斥量解決生產者消費者問題

    Posix信號量 Posix 信號量 有名信號量 無名信號量 sem_open sem_init sem_close sem_destroy sem_unlink   sem_wait sem_post   有名信號量   與Posix類IPC用法類似: 名字以/somename形式標識,且只能有一個/ ,并且總長不能超過NAM...

    UCOSIII信號量與互斥量

    在 UCOSIII 中有可能會有多個任務會訪問共享資源,因此信號量最早用來控制任務存取共享資源,現在信號量也被用來實現任務間的同步以及任務和 ISR 間同步。在可剝奪的內核中,當任務獨占式使用共享資源的時候,會出現低優先級的任務先于高優先級任務運行的現象,這個現象被稱為優先級反轉,為了解決優先級反轉這個問題,UCOSIII 引入了互斥信號量這個概念。 信號量 信號量像是一種上鎖機制,代碼必須獲得對...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    猜你喜歡

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    精品国产乱码久久久久久蜜桃不卡