使用互斥鎖解決生產者與消費者問題

來源:互聯網
上載者:User
互斥鎖:上鎖與解鎖

互斥鎖指代相互排斥,是最基本的同步形式,它可用於保護臨界取,以保證任何時刻只有一個線程在執行其中的代碼。它可以用來同步一個進程內的各個線程。如果互斥鎖存放在多個進程間共用的某個記憶體區中,它也可以用於這些進程間的同步。它實際上保護的是臨界區中被操縱的資料,也就是保護由多個線程或多個進程分享的共用資料


使用方法

lock_the_mutex(...)

臨界區

unlock_the_mutex(,,,)

在Posix中,互斥鎖聲明為具有pthread_mutex_t資料類型的變數


相關函數

#include <pthread.h>

int pthread_mutex_init (pthread_mutex_t * mutex, const pthread_mutexattr_t *mutexattr) //動態建立

int pthread_mutex_destroy (pthread_mutex_t * mutex)   //銷毀互斥量

int pthread_mutex_lock(pthread_mutex_t  *mutex);    //上鎖

int pthread_mutex_trylock(pthread_mutex_t  *mutex);  //非阻塞解鎖

int pthread_mutex_unlock(pthread_mutex_t  *mutex);  //阻塞解鎖

如果嘗試給一個已由某個線程鎖住的互斥鎖上鎖,那麼pthread_mutex_lock將阻塞到該互斥鎖解鎖為止。pthread_mutex_trylock是對應的非阻塞函數。如果該互斥鎖已鎖住。它就返回一個EBUSY錯誤

解決生產者與消費者問題

 多個生產者一個消費者,如


整數數組buff含有被生產和消費的條目(也就是共用資料),buff資料從0開始遞增

線程間的共用的全域變數


設定並發線程層級

 調用pthread_setconcurrency,當我們希望多個生產者線程中每一個都有執行機會時,這個函數是必須的

命令列參數

 第一個命令列參數指定生產者存放的條目數,下一個參數指定建立生產者線程的數目


具體實現代碼

#include <pthread.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#define MAXNITEMS  10000#define MAXNTHREADS 20int nitems;    //read-only by producer and consumerstruct {pthread_mutex_t  mutex;int buff[MAXNITEMS];int nput;int nval;}shared =        //initialized staticly{PTHREAD_MUTEX_INITIALIZER};void *producer(void *);void *consumer(void *);int min(int a, int b) { return a<b ? a : b; }int main(int argc, char *argv[]){int i, nthreads, count[MAXNTHREADS];pthread_t tid_produce[MAXNTHREADS], tid_consume;if(argc!=3){printf("usage: ProCon <#items> <#threads>");exit(1);}nitems = min(atoi(argv[1]), MAXNITEMS);nthreads = min(atoi(argv[2]), MAXNTHREADS);pthread_setconcurrency(nthreads);for(i=0; i<nthreads; i++){count[i] = 0;pthread_create(&tid_produce[i], NULL, producer, &count[i]);}//wait for all the producer threadsfor(i=0; i<nthreads; i++){pthread_join(tid_produce[i], NULL);printf("count[%d] = %d\n", i, count[i]);}//start, then wait for the consumer threadpthread_create(&tid_consume, NULL, consumer, NULL);pthread_join(tid_consume, NULL);return 0;}void *producer(void * arg){for(; ; ){pthread_mutex_lock(&shared.mutex);if(shared.nput >= nitems){pthread_mutex_unlock(&shared.mutex);return (NULL);//array is full, we're done}shared.buff[shared.nput] = shared.nval;shared.nput++;shared.nval++;pthread_mutex_unlock(&shared.mutex);*((int *)arg) += 1;}}void *consumer(void *arg){int i;for(i=0; i<nitems; i++){if(shared.buff[i]!=i){printf("buff[%d] = %d\n", i, shared.buff[i]);}}return NULL;}

代碼解釋

  39-42行用來建立消費者線程,每個線程執行producer函數,在tid_produce數組中儲存每個線程的線程ID。等待所有生產者線程結束後,再啟動消費者線程。在生產者線程結束的同時輸出每個線程的計數值,即線程的執行次數。

注意:count元素的增加不屬於臨界區,因為每個線程有各自的計數器。

運行結果如下


如果去掉互斥鎖的話,結果就會輸出buff的錯誤值(當items比較大小),

我在ubuntu上的測試結果 ./ProCon 400 5


 註:該博文為<<unix網路編程 --卷二>>讀書筆記

聯繫我們

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