您好,登錄后才能下訂單哦!
這篇文章主要介紹“C語言并發編程模型實例分析”,在日常操作中,相信很多人在C語言并發編程模型實例分析問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C語言并發編程模型實例分析”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
我們執行兩個線程:foo1和foo2
foo1:打印step1, step3
foo2:打印step2
請用并發使得按照1 2 3 的順序輸出
答:首先兩個線程執行順序不可預判,我們必須保證打印step2之前step1就打印好了,因此需要阻塞一下step2,實現的方式是初始化sem為0,只有打印完step1后(然后進行解鎖,V操作)step2才能執行
同理,只有打印完step2后才解開阻塞step3的鎖,具體看代碼實現就明白了
#include "csapp.c" sem_t step1_done, step2_done; void* foo1() { printf("test1 is done\n"); V(&step1_done); //step1執行完畢了,那么foo2的阻塞就會被解開 P(&step2_done); //測試是否step2執行完畢, printf("test3 is done\n"); return NULL; } void* foo2() { P(&step1_done); printf("test2 is done\n"); V(&step2_done); //step2執行完畢,解開打印step的鎖 return NULL; } int main() { pthread_t tid1, tid2; Sem_init(&step1_done, 0, 0); //第二個參數為0:在線程之間進行, 第三個參數初始化都為零 Sem_init(&step2_done, 0, 0); Pthread_create(&tid1, NULL, foo1, NULL); Pthread_create(&tid2, NULL, foo2, NULL); //保證線程執行完畢之后主線程才退出,否則線程都執行不了了 Pthread_join(tid1, NULL); Pthread_join(tid2, NULL); exit(0); }
主要的就是在生產和消費函數中對于信號量的處理
錯誤實例:
void sbuf_insert(subf_t* sp, int item) { sem_wait(&sp->mutex); sem_wait(&sp->slots); //將項目放進buf中 sp->buf[(++sp->rear) % (sp->n)] = item; sem_post(&sp->items); sem_post(&sp->mutex); } void sbuf_remove(sbuf_t* sp) { sem_wait(&sp->mutex); sem_wait(&sp->items); //do works sem_post(&sp->slots); sem_post(&sp->mutex); }
如果我們在處理的時候先拿到 互斥鎖,可能就會引起死鎖
假設現在buf是滿的,生產者拿到了互斥鎖,但是自己因為沒有空閑被 block…
此時消費者同樣因為拿不到互斥鎖而被 block…
其他的生產者同樣也是沒有 互斥鎖被block…
解決方法:
比較簡單,調換一下順序就好了。相當于我們生產者、消費者在進行的時候 明確我到底要操控哪個格子 然后再拿mutex????
#include <stdio.h> #include <stdlib.h> #include <semaphore.h> typedef struct sbuf{ int *buf; /*堆上開辟的內存,用于存儲*/ int n; /*cap of the buf*/ int front; //第一個item int rear; //最后一個item sem_t mutex; //獲取臨界區的鎖 sem_t slots; //空槽數目 sem_t items; //已經生產了的數目 }subf_t; void sbuf_init(subf_t* sp, int n) { sp->n = n; sp->buf = static_cast<int *>(calloc(n, sizeof(int))); sp->front = 0; sp->rear = 0; sem_init(&sp->mutex, 0, 1); sem_init(&sp->slots, 0, n); sem_init(&sp->items, 0, 0); } void sbuf_deinit(subf_t*sp) { free(sp->buf); } void sbuf_insert(subf_t* sp, int item) { //首先應該對信號量slots判斷,你生產者看中 sem_wait(&sp->slots); sem_wait(&sp->mutex); //將項目放進buf中 sp->buf[(++sp->rear) % (sp->n)] = item; //CSAPP中提到,解鎖的順序一般是和加鎖的順序是相反的 sem_post(&sp->mutex); sem_post(&sp->items); } int sbuf_remove(subf_t* sp) { int item; sem_wait(&sp->items); //我看上哪個格子的產品了 sem_wait(&sp->mutex); item = sp->buf[(++sp->front) % (sp->n)]; sem_post(&sp->mutex); sem_post(&sp->slots); return item; }
第一類讀者、寫者問題(讀者優先)
不會讓讀者進行等待的,除非現在的權限是寫者的
也就是說讀者不會因為有一個寫者在等待
實現:
信號量:w維護著對于critical section的訪問, mutex維護這對于共享變量readcnt(當前在臨界區的讀者的數量)的訪問
每當寫者進入了臨界區,就對w進行加鎖????,離開就解鎖。保證了任意時刻臨界區最多只能有一個寫者
只有第一個讀者進入的時候對W加鎖,最后一個才釋放,那么只要還有一個讀者在,其他任意的讀者就能夠無障礙的進入,同樣會導致 寫者饑餓
int readcnt = 0; sem_t ,mutex = 1, w = 1; void reader() { while (1) { P(&mutex); readcnt++; if (readcnt == 1) //第一個進入的讀者 P(&w); //上鎖,寫者不能寫了 V(&mutex); //解開對于readcnt的保護鎖 /* 臨界區的工作 */ P(&mutex); readcnt--; if (readcnt == 0) V(&w); //最后一個讀者了, 解開阻塞寫者的鎖 V(&mutex); //解開對readcnt的保護鎖 } } void writer() { while (1) { P(&w); /* 臨界區工作 */ V(&w); } }
到此,關于“C語言并發編程模型實例分析”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。