• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • Linux系統編程之線程控制及線程間同步互斥機制:POSIX信號量和互斥鎖

    聲明:侵刪

    1. 線程和進程的區別

    進程 :每個進程有自己獨立的地址空間
    Linux為每個進程創建task_struct (任務結構體,存放進程屬性)
    每個進程都參與內核調度,不影響其他進程

    線程:進程在切換時系統開銷大
    很多操作系統引入了輕量級進程LWP(線程)
    同一進程中的線程共享相同地址空間
    Linux不區分進程、線程(Linux都認為成一個任務)
    一個進程中的多個線程共享一下資源
    線程ID
    PC和相關寄存器
    堆棧
    errno
    優先級
    執行狀態和屬性

    2.prhread線程庫相關API

    編譯時候要注意鏈接pthread線程庫

    線程創建函數:pthread_creat
    在這里插入圖片描述線程回收函數: pthread_join
    在這里插入圖片描述線程退出函數:pthread_exit
    在這里插入圖片描述

    3.線程間的同步和互斥

    線程共享進程的空間地址和資源,對這些資源進行操作是必須注意線程間的同步和互斥。本文主要介紹POSIX的兩種互斥機制: 信號量和互斥鎖。
    互斥鎖適用于同時可用資源唯一的情況,信號量適合于同時可用資源為多個的情況。

    4.互斥鎖

    互斥鎖是一種以簡單的加鎖方式對共享資源的原子操作。互斥鎖有兩種狀態:上鎖和解鎖。在同一時刻只有一個線程可以掌握互斥鎖,擁有上鎖狀態的線程可以對共享資源進行操作,其余線程想要搶鎖就會掛起直到擁有鎖的進程釋放鎖。
    互斥鎖可以分為快速互斥鎖、遞歸互斥鎖、檢錯互斥鎖。
    快速鎖:調用線程必須堵塞到擁有鎖的進程釋放鎖為止
    遞歸鎖:遞歸鎖能夠成功的返回,并能增加調用線程在互斥上加鎖的次數
    檢錯鎖:相當于非堵塞版的快速鎖,搶不到鎖不會堵塞會返回一個錯誤信息。
    默認是快速互斥鎖。
    使用互斥鎖之前必須初始化鎖的類型。
    互斥鎖相關API

    互斥鎖初始化函數 pthread_mutex_init
    在這里插入圖片描述
    互斥鎖控制函數:上鎖、解鎖、檢查鎖、刪除鎖、
    在這里插入圖片描述

    5.互斥鎖例程

    /*mutex.c*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    
    
    #define THREAD_NUM  3 /*線程數*/
    #define TASKK_NUM   3  /*每個線程執行的小任務數*/
    #define DELAY_TIME  10 /*每個小任務最大時間間隔*/
    pthread_mutex_t mutex; /*定義互斥鎖*/
    
    /*線程函數*/
    void * func_thread(void *arg)
    {
        int thread_num = (int) arg;
        int delay_time = 0;
        int count = 0;
        if (pthread_mutex_lock(&mutex) == -1)/*搶鎖*/
        {
            perror("pthread_mutex_lock");
            pthread_exit(NULL);
        }
        printf("The thread [%d] is beginning\n",thread_num);
        for(count = 0; count<TASKK_NUM;count++)    
        {
            delay_time =(int)(rand()%DELAY_TIME)+1; /*產生隨機數1-DLY_TIME*/
            sleep(delay_time);
            printf("\tthread[%d],job[%d],sleep[%d]s\n",thread_num,count,delay_time);
    
        }
        printf("pthread[%d] end\n",thread_num);
        pthread_mutex_unlock(&mutex);/*解鎖*/
        pthread_exit(NULL);
    }   
    int main()
    {
        pthread_t tid[THREAD_NUM];
        int thread_num =0 ;
    
        srand((time(NULL))); /*初始化隨機數種子*/
        pthread_mutex_init(&mutex,NULL);/*初始化互斥鎖為快速互斥鎖*/
    
        /*創建線程*/
        for( thread_num=0;thread_num < THREAD_NUM;thread_num ++)
        {
            if (pthread_create(&tid[thread_num],NULL,func_thread,(void *) thread_num) != 0)
            {
                printf("Create pthread[%d]  failed\n",thread_num);
                exit(-1);
            }
        }
    
        printf("Creat all thread sucessed,please waitting ...\n" );
        /*回收進程*/
        for(thread_num = 0;thread_num <THREAD_NUM;thread_num++)
        {
            pthread_join(tid[thread_num],NULL);
            printf("thread[%d]  joined\n",thread_num);
        }
        pthread_mutex_destroy(&mutex); /*刪除鎖*/
        exit(1);
    
    
    }
    

    結果對比
    在這里插入圖片描述

    6.POISX信號量 System V 信號量參考此文

    信號量實質是一個非負整數的計數器,是操作系統中的PV原語,常用于線程間的同步與互斥。
    一次 P 操作使信號量sem 減 1, 而一次 V 操作使 sem 加 1。 進程( 線程) 根據信號量的值來判斷是否對公共資源具有訪問權限。當 sem 的值大于等于 0 時,該進程(或線程)具有公共資源的訪問權限;相反,當 sem 的值小于 0 時,該進程(線程)就將阻塞直到 sem 的值大于等于 0 為止。
    信號量常用語進程(線程)之間的同步或者互斥
    互斥 當信號量作互斥作用時,往往設置一個信號量來決定資源歸屬
    在這里插入圖片描述
    同步信號量做同步機制時,往往設置多個信號量,通過初始化值和PV操作來決定他們的運行順序。


    POSIX信號量相關API
    信號量創建初始化函數 sem_init
    在這里插入圖片描述
    信號量操作函數 PV操作、刪除、獲取信號量的值
    在這里插入圖片描述**

    7.POSIX信號量例程

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <string.h>
    #include <semaphore.h>
    
    #define THREAD_NUM  3 /*線程數*/
    #define TASKK_NUM   3  /*每個線程執行的小任務數*/
    #define DELAY_TIME  10 /*每個小任務最大時間間隔*/
    
    
    sem_t sem[THREAD_NUM];
    
    /*線程函數*/
    void * func_thread(void *arg)
    {
        int thread_num = (int) arg;
        int delay_time = 0;
        int count = 0;
        /*每個線程首先進行P操作 ,判斷有無資源*/
        sem_wait(&sem[thread_num]);
        printf("The thread [%d] is beginning\n",thread_num);
        for(count = 0; count<TASKK_NUM;count++)    
        {
            delay_time =(int)(rand()%DELAY_TIME)+1; /*產生隨機數1-DLY_TIME*/
            sleep(delay_time);
            printf("\tthread[%d],job[%d],sleep[%d]s\n",thread_num,count,delay_time);
        }
        printf("pthread[%d] end\n",thread_num);
    
        pthread_exit(NULL);
    }   
    int main()
    {
        pthread_t tid[THREAD_NUM];
        int thread_num =0 ;
    
        srand((time(NULL))); /*初始化隨機數種子*/
    
    
        /*創建線程*/
        for( thread_num=0;thread_num < THREAD_NUM;thread_num ++)
        {
            sem_init(&sem[thread_num],0,0);/*將所有信號量初始化為0*/
            if (pthread_create(&tid[thread_num],NULL,func_thread,(void *) thread_num) != 0)
            {
                printf("Create pthread[%d]  failed\n",thread_num);
                exit(-1);
            }
        }
        /*將最后創建的一個進程進行V操作, sem[THREAD_NUM-1]變為1,最后創建的進程先運行*/
        sem_post(&sem[THREAD_NUM-1]);
        printf("Creat all thread sucessed,please waitting ...\n" );
        /*回收進程*/
        for(thread_num = THREAD_NUM -1;thread_num >= 0;thread_num --)
        {
            pthread_join(tid[thread_num],NULL);
            printf("thread[%d]  joined\n",thread_num);
            /*每回收一個線程就將下一個要運行線程解開,對上一個信號量V操作*/
            sem_post(&sem[(thread_num+THREAD_NUM-1)%THREAD_NUM]);
        }
        /*刪除信號量*/
        for(thread_num = 0;thread_num <THREAD_NUM-1;thread_num++)
        {
            sem_destroy(&sem[thread_num]);
        }
        exit(1);
    
    
    }
    

    結果
    在這里插入圖片描述

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

    智能推薦

    線程的同步控制---信號量、互斥鎖、條件變量

    一、線程同步 原因:線程之間擁有許多共享資源,當此資源被多個線程進行訪問時容易造成數據錯誤,程序崩潰,所以需要對線程的臨界資源進行同步控制。 同步:多進程和多線程訪問臨界資源時,需要進行同步控制。多線程或者多進程的執行并不會完全的并行運行,有可能主線程需要等待函數線程的某些條件的發生。 多線程之間臨界資源: 全局數據 堆區數據文件描述符 線程之間的同步控制方式: 3.1信號量 #include&l...

    【Linux】深入理解線程(線程同步、互斥量mutex、死鎖、讀寫鎖、條件變量、信號量)

    一、同步概念        1、線程同步:             同步即協同步調,按預定的先后次序運行。             線程同步,只一個線程發出某一功能調用時,在沒有得到結果之前,該調用不返回。同時,其他線程為保證數據一致性,不...

    使用信號量控制線程互斥和同步。

    首先要知道PV原語的概念。以下是百度百科對PV原語的介紹: PV原語通過操作信號量來處理進程間的同步與互斥的問題。其核心就是一段不可分割不可中斷的程序。 信號量的概念1965年由著名的荷蘭計算機科學家Dijkstra提出,其基本思路是用一種新的變量類型(semaphore)來記錄當前可用資源的數量。有兩種實現方式:1)semaphore的取值必須大于或等于0。0表示當前已沒有空閑資源,而正數表示當...

    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_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

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