多線程之互斥鎖、條件變數

來源:互聯網
上載者:User

標籤:互斥   鎖   多線程   同步   記憶體   

多線程

一個進程在同一時刻只能做一件事,而多個線程卻可以同時執行,每個線程處理各自獨立的任務。多線程有很多好處:

  • 簡化處理非同步事件的代碼
  • 實現記憶體和檔案描述符的共用
  • 改善程式的輸送量
  • 改善回應時間
互斥鎖

互斥鎖:互斥鎖通過鎖機制來實現線程間的同步,在同一時刻通常只允許一個關鍵區段的代碼

當多個線程式控制制相同的記憶體時,對於讀寫操作的時間差距就有可能會導致資料的不同步,就很清晰的說明了這種情況:

對於線程A、B此時對同一塊記憶體進行操作,但是由於操作幾乎是同時進行的,假設當線程A讀入資料i之後,在對資料 i 自加1的同時線程B將原來記憶體中的資料 i 讀出,然後線程A將自加後的資料再寫入記憶體中,同時線程B對讀取到的 i 加1,最後將其寫入記憶體,這個程式原本是想通過兩個線程對變數 i 進行兩次自加運算最後預想的結果應當是7,最後卻得到異常的結果。對於這種臨界變數操作時就有可能導致意外的結果,因而出現了互斥鎖和條件變數來保證資料只被一個線程操作。

下面程式的運行結果也很好的說明了多線程操作同一變數不穩定性:

#include<stdio.h>#include<stdlib.h>#include<pthread.h>#include<errno.h>int a = 0;      //用作要改變的全域變數pthread_mutex_t mutex;  //互斥鎖變數void thread1(void *arg){    //pthread_mutex_lock (&mutex); //加鎖    printf("thread1 a = %d\n", a);    a++;    //pthread_mutex_unlock (&mutex);}void thread2(void *arg){    //pthread_mutex_lock (&mutex);    printf("thread2 a = %d\n", a);    a++;    //pthread_mutex_unlock (&mutex);}void thread3(void *arg){    //pthread_mutex_lock (&mutex);    printf("thread3 a = %d\n", a);    a++;    //pthread_mutex_unlock (&mutex);}int main(void){    pthread_t tid1, tid2, tid3;   //用於接收線程ID    int       err;                //出錯碼    void *    tret;               //傳回值    //建立三個線程    pthread_create (&tid1, NULL, (void *)thread1, NULL);    pthread_create (&tid2, NULL, (void *)thread2, NULL);    pthread_create (&tid3, NULL, (void *)thread3, NULL);    //等待輔線程結束    err = pthread_join(tid1, &tret);    if(err != 0)    {        perror("join");    }    err = pthread_join(tid2, &tret);    if(err != 0)    {        perror("join");    }    err = pthread_join(tid3, &tret);    if(err != 0)    {        perror("join");    }    printf("result a: %d\n", a);   //查看最後的結果    exit(0);}

多次執行結果如下:

發現幾次的執行結果並不相同,本來程式是通過三個線程對同一個全域變數進行3次加1的操作結果應當為0, 1,2,3,由於線程間資料不同步所以導致了這樣的結果。

當前我們將程式中各個thread函數中的注釋取消之後就會得到這樣的結果:

這裡就體現了互斥鎖來保證線程間資料的同步。

使用互斥鎖應當注意:

  1. 使用之前必須進行初始化
  2. 加鎖時,若鎖變數已經被鎖住,則當前嘗試加鎖的線程就會阻塞,直到互斥鎖被其他線程釋放
  3. 調用解鎖函數的線程必須是給互斥鎖加鎖的線程
  4. 當一個線程試圖以另一個線程相反的順序鎖住互斥量的時候,就有可能出現死結
  5. 如果線程試圖對一個互斥量加鎖兩次,那麼它自身就會陷入死結狀態

死結:指兩個或兩個以上的進程在執行過程中,由於競爭資源或者由於彼此通訊而造成的一種阻塞的現象,若無外力作用,它們都將無法推進下去。此時稱系統處於死結狀態或系統產生了死結,這些永遠在互相等待的進程稱為死結進程

條件變數

條件變數:是利用線程間共用的全域變數進行同步的一種機制
使用條件變數要注意:

  1. 使用之前要初始化
  2. 條件變數通常是在互斥鎖的保護下求值,若條件運算式為假,那麼線程基於條件變數阻塞。
  3. 線程被條件變數阻塞後,可以通過pthread_cond_signal和pthread_cond_broadcast啟用,pthread_cond_signal啟用按照入隊順序啟用一個等待線程,pthread_cond_broadcast則啟用所有的等待線程
  4. 當一個條件變數不再使用時,需要將其清除,清除函數:pthread_cond_destory,只有在沒有線程等待該條件變數的時候才能清除這個條件變數,否則返回EBUSY。
  5. 調用pthread_cond_wait()前必須有本線程加鎖,防止多個線程同時請求pthread_cond_wait()。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

多線程之互斥鎖、條件變數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.