GNU/Linux中解決多線程互斥同步問題

來源:互聯網
上載者:User
當解決多線程互斥同步的問題時,經常會有如下幾個問題:

1. 在一個給定的問題中,需要多少個Mutex,多少個Semaphore?有什麼規律?
2. 在對臨界區加鎖和等待訊號量的順序上有什麼要求和規律?
3. 什麼樣操作適合放在臨界區,什麼樣的不適合?

下面就生產者和消費者問題來分析一些這幾個問題.
下面是一個簡單的實現程式:
生產者向數組sharedArray中寫入資料,而消費者從該數組中讀取資料.

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>

#define MAXSIZE  5               /*共用緩衝區的大小*/

int sharedArray[MAXSIZE];        /*sharedArray是共用緩衝區*/
int curr=-1;                     /*curr是用來指定sharedArray當前存有資料的最大位置*/
                                 /*注意,sharedArray和curr都屬於共用資料*/

int empty=0;            
int full=MAXSIZE;
pthread_mutex_t sharedMutex=PTHREAD_MUTEX_INITIALIZER; /*鎖定臨界區的mutex*/
sem_t waitNonEmpty, waitNonFull; /*等待"非空資源"和等待"非滿資源"的semaphor*/

void * readData(void * whichone)
{
        int data, position;
        while (1){
                sem_wait(&waitNonEmpty);             /*是否有"非空資源"*/

                pthread_mutex_lock(&sharedMutex);    /*進入臨界區*/
                data = sharedArray[curr];
                position = curr--;
                printf ("%s read from the %dth: %d, /n", (char*)whichone, position, data);
                sem_post(&waitNonFull);              /*產生一個"非滿資源"*/
                pthread_mutex_unlock(&sharedMutex);  /*離開臨界區*/

                sleep(2);                            /*跟同步無關的費時操作*/
        }
}

void * writeData(void * whichone)
{
        int data, position;
        while (1) {
                data=(int)(10.0*random()/RAND_MAX);    /*產生一個隨機資料,注意是10.0而不是10*/
                sem_wait(&waitNonFull);                /*是否有"非滿資源"*/

                pthread_mutex_lock(&sharedMutex);      /*進入臨界區*/
                position = ++curr;
                sharedArray[curr]=data;
                printf ("%s wrote to the %dth: %d, /n", (char*)whichone, position, data);
                sem_post(&waitNonEmpty);               /*產生一個"非空資源"*/
                pthread_mutex_unlock(&sharedMutex);    /*離開臨界區*/

                sleep(1);                              /*跟同步無關的費時操作*/

        }
}

int main (int argc, char** argv)
{
        pthread_t consumer1, consumer2, producer1, producer2;    /*兩個生產者和兩個消費者*/
        sem_init(&waitNonEmpty, 0, empty);                       /*初始化訊號量*/
        sem_init(&waitNonFull, 0, full);            
        /*注意,本問題中的兩種semaphore是有一定關係的,那就是它們的初始值之和應該等於共用緩衝區大小*/
        /*即empty+full等於MAXSIZE*/

        pthread_create (&consumer1, NULL, &readData, "consumer1");
        pthread_create (&consumer2, NULL, &readData, "consumer2");
        pthread_create (&producer1, NULL, &writeData, "producer1");
        pthread_create (&producer2, NULL, &writeData, "producer2");
        pthread_join (consumer1, NULL);
        pthread_join (consumer2, NULL);
        pthread_join (producer1, NULL);
        pthread_join (producer2, NULL);
        sem_destroy(&waitNonEmpty);
        sem_destroy(&waitNonFull);

}

分析和說明:

1. 在一個給定的問題中,需要多少個Mutex,多少個Semaphore?有什麼規律?

在本問題中,共需要一個Mutex和兩個Semaphore.
其中,Mutex是用來鎖定臨界區的,以解決對共用資料的互斥訪問問題(無論是對產生者還是對消費者);
我們共需要兩個Semaphore,這是因為在本問題中共有兩個稀缺資源.
第一種是"非空"這種資源,是在消費者之間進行競爭的.
第二種是"非滿"這種資源,是在生產者之間進行競爭的.
所以,一般來說,需要鎖定臨界區,就需要Mutex;有幾種稀缺資源就需要幾個Semaphore.
對稀缺資源的分析不能想當然.稀缺資源不一定是指被共用的資源,很多時候是指線程會被阻塞的條件(除了要進臨界區被阻塞外).
本例中,消費者會在緩衝區為空白時被阻塞,所以"非空"是一種稀缺資源;
生產者會在緩衝區為滿時被阻塞,所以"非滿"也是一種稀缺資源.

2. 在對臨界區加鎖和等待訊號量的順序上有什麼要求和規律?

這裡要說兩點:
第一,不要將等待訊號量的語句放在被鎖定的臨界區內,這樣會造成死結.而且這也是很沒有必要的.
比如,消費者在緩衝區沒有資料的時候進入臨界區,這樣就會把臨界區鎖上,由於沒有資料,消費者也會被鎖上.
這時,任何生產者都會由於臨界區被鎖上而被block住,這樣就造成了死結.
第二,如果有多個Semaphore需要等待,那麼每個線程中,最好對這多個訊號量進行等待的順序一致,
不然的話很容易造成死結.

3.  什麼樣操作適合放在臨界區,什麼樣的不適合?

一般來說,臨界區中只放對共用資料進行訪問的語句,這樣會改善程式的效能.
很多時候,取出共用資料的副本後,對副本進行費時的各種操作就不需要放在臨界區了.
比如,本例中的sleep語句就根本不需要放入臨界區.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.