• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • 線程同步與互斥。(互斥量與條件變量、Posix信號量)

    線程互斥:
    所謂互斥:即是間接制約關系,指系統中的某些共享資源,一次只允許一個線程訪問,當一個線程正在訪問該臨界資源時,其它線程必須等待。

    mutex(互斥量):

    • 互斥量本身也是一把鎖,提供對資源的獨占訪問。
    • 大部分情況下,線程使用的數據都是局部變量,變量的地址空間在線程棧空間內,變量歸屬于某個單個線程,其它線程無法獲得這種變量。
    • 共享變量:很多變量需要在線程間共享,可以通過數據的共享,完成數據間的交互。

      下面我們來看一個買票問題(沒加互斥量之前)

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<unistd.h>
      4 #include<pthread.h>
      5 
      6 int ticket=100;
      7 
      8 void*thread_run(void*arg)
      9 {
     10         int a=(int)arg;
     11         while(1){
     12                 if(ticket>0){
     13                         usleep(10000);
     14                         printf("%d sells ticket:%d\n",a ,ticket);
     15                         ticket--;
     16                 }else{
     17                         break;
     18                 }
     19         }
     20 }
     21 int main()
     22 {
     23         pthread_t t1,t2,t3,t4;
     24         void*ret1;
     25         void*ret2;
     26         void*ret3;
     27         void*ret4;
     28         pthread_create(&t1,NULL,thread_run,(void*)1);
     29         pthread_create(&t2,NULL,thread_run,(void*)2);
     30         pthread_create(&t3,NULL,thread_run,(void*)3);
     31         pthread_create(&t4,NULL,thread_run,(void*)4);
     32 
     33         pthread_join(t1,&ret1);
     34         pthread_join(t2,&ret2);
     35         pthread_join(t3,&ret3);
     36         pthread_join(t4,&ret4);
     37 }
    

    結果顯示:
    這里寫圖片描述
    因為每個線程取票的過程并不是原子性的。

    下面來看看互斥量的接口;
    - 初始化互斥量:

    • 方法一:靜態分配:
    pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER
    • 方法二:動態分配:
    int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
        參數解釋:mutex:要初始化的互斥量。
                attr:NULL
    

    - 銷毀互斥量:
    1.靜態分配的互斥量不需要銷毀。
    2.不要銷毀一個已經加鎖的互斥量。
    3.已經銷毀的互斥量,要確保后面的不會有線程再嘗試加鎖。

    int pthread_mutex_destroy(pthread_mutex_t *mutex);

    互斥量的加鎖與解鎖:

    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);

    返回值:成功返回0,失敗返回錯誤號。
    則可改進上邊的售票系統:

      1 #include<stdio.h>
      2 #include<stdlib.h>
      3 #include<unistd.h>
      4 #include<pthread.h>
      5 
      6 int ticket=100;
      7 pthread_mutex_t mutex;
      8 
      9 void*thread_run(void*arg)
     10 {
     11         int a=(int)arg;
     12         while(1){
     13                 pthread_mutex_lock(&mutex);//加鎖
     14                 if(ticket>0){
     15                         usleep(10000);
     16                         printf("%d sells ticket:%d\n",a ,ticket);
     17                         ticket--;
     18                         pthread_mutex_unlock(&mutex);//解鎖
     19                 }else{
     20 
     21                         pthread_mutex_unlock(&mutex);//解鎖
     22                         break;
     23                 }
     24         }
     25 }
     26 int main()
     27 {
     28         pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//初始化互斥量
     29         pthread_t t1,t2,t3,t4;
     30         void*ret1;
     31         void*ret2;
     32         void*ret3;
     33         void*ret4;
     34         pthread_create(&t1,NULL,thread_run,(void*)1);
     35         pthread_create(&t2,NULL,thread_run,(void*)2);
     36         pthread_create(&t3,NULL,thread_run,(void*)3);
     37         pthread_create(&t4,NULL,thread_run,(void*)4);
     39         pthread_join(t1,&ret1);
     40         pthread_join(t2,&ret2);
     41         pthread_join(t3,&ret3);
     42         pthread_join(t4,&ret4);
     43 }
    

    運行結果:

    這里寫圖片描述
    線程同步:
    1. 條件變量
    - 當一個線程互斥地訪問某個變量時,它可能發現在其他線程改變狀態之前,它什么也做不了。
    - 例如一個線程訪問隊列時,發現隊列為空,它只能等待。直到其他線程將一個節點添加到隊列中。
    - 所以條件變量相當于一個中介。如一個搶答器,兩人同時按其的過程。
    - 多線程條件下通知某些事件已經就緒的方式。

    條件變量函數:
    初始化:

    int pthread_cond_init(pthread_cond_t *cond,const pthread_condattr_t *attr);
    參數:
        cond:要初始化的條件變量
        attr:NULL

    銷毀:int pthread_cond_destroy(pthread_cond_t *cond)
    等待條件滿足:

    int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
    參數:
        cond:要在此條件變量上等待
        mutex:互斥量,因為在等待時需要將鎖釋放掉。

    喚醒條件:

    int pthread_cond_signal(pthread_cond_t *cond);

    一個簡單的案例:

    1 #include<stdio.h>
      2 #include<pthread.h>
      3 #include<unistd.h>
      4 #include<string.h>
      5 #include<stdlib.h>
      6 
      7 pthread_cond_t cond;
      8 pthread_mutex_t mutex;
      9 
     10 void*r1(void*arg)
     11 {
     12         while(1){
     13                 pthread_cond_wait(&cond,&mutex);
     14                 printf("hello\n");
     15         }
     16 }
     17 void *r2(void*arg)
     18 {
     19         while(1){
     20                 pthread_cond_signal(&cond);
     21                 sleep(1);
     22         }
     23 }
     24 int main()
     25 {
     26         pthread_t t1,t2;
     27         pthread_mutex_init(&mutex,NULL);
     28         pthread_create(&t1,NULL,r1,NULL);
     29         pthread_create(&t2,NULL,r2,NULL);
     30         pthread_join(t1,NULL);
     31         pthread_join(t2,NULL);
     32         pthread_mutex_destroy(&mutex);
     33         pthread_cond_destroy(&cond);
     34 }
    ~     

    運行結果顯示:(每隔1秒打印一個hello world)
    這里寫圖片描述
    2. POSIX信號量(用于實現線程同步)
    初始化信號量:

    #include<semaphore.h>
    int sem_init(sem_t *sem,int pshared,unsigned int value);
    參數:
         pshared:0表示線程間共享,非0表示進程間共享
         value:信號量初始值。

    申請信號量不成功時,則申請的線程會被掛起。
    銷毀信號量:

    #include<semaphore.h>
    int sem_destroy(sem_t *sem)

    等待信號量(p操作)

    功能:會將信號量的值減1
    int sem_wait(sem_t *sem);

    發布信號量(v操作)

    功能:表示資源使用完畢,可以歸還資源了,將信號量值加1.
    int sem_post(sem_t *sem)

    好了,具體的代碼會在下篇博客生產者、消費者模型中呈現。

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

    智能推薦

    【Linux】線程互斥量與條件變量

    一.互斥量(mutex) 1.基本概念 在線程之間,因為線程組內所有線程共享進程的地址空間,所以對于每個線程來說,它的絕大多數資源都是與其他線程共享的,所以在多線程程序中,極有可能因為多個線程同時訪問臨界資源,而造成數據的二義性問題。所以這里就引入了同步與互斥機制來保護臨界資源 大部分情況,線程使用的數據都是局部變量,變量的地址空間在線程棧空間內,這種情況,變量歸于單個線程,其他線程語法獲得者種變...

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

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

    09_線程同步_互斥鎖_讀寫鎖_條件變量_信號量

    目錄 1. 概念 1.1、線程同步 1.2、臨界資源 1.3、臨界區 2. 互斥鎖(互斥量) 2.1、互斥鎖類型? 2.2、互斥鎖特點? 2.3、互斥鎖相關函數 3. 死鎖 3.1、死鎖 的幾種場景 3.1.1、忘記釋放鎖,自己將自己鎖住 3.1.2、單線程重復申請鎖 3.1.3、多線程多鎖申請, **搶占鎖資源** 3.2、死鎖的解決 4. 讀寫鎖 1.讀寫鎖類型? 是幾把鎖? 2.讀寫鎖的特點...

    linux學習---線程同步(互斥量,信號量,條件量)線程屬性

    進程   系統中程序執行和資源分配的基本單位   每個進程有自己的數據段、代碼段和堆棧段   在進行切換時需要有比較復雜的上下文切換 線程   減少處理機的空轉時間,支持多處理器以及減少上下文切換開銷, 比創建進程小很多   進程內獨立的一條運行路線   處理器調度的最小單元,也稱為輕量級進程        可以對進程的內存空間和資源進行訪問,并與同一進程中...

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

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

    猜你喜歡

    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壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

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