生產者消費者模型/條件變數
阿新 • • 發佈:2021-09-28
生產者消費者模型(簡略)
//效率不高,引入條件變數 #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> // 建立一個互斥量 pthread_mutex_t mutex; struct Node { int num; struct Node * next; }; struct Node * head = NULL; void* producer(void * arg) { //不斷創造新的節點 while(1){ pthread_mutex_lock(&mutex); struct Node* newNode = (struct Node *)malloc(sizeof(struct Node)); newNode->next = head; head = newNode; newNode->num = rand()%1000; printf("add node ,num :%d, tid : %ld\n",newNode->num,pthread_self()); pthread_mutex_unlock(&mutex); usleep(100); } return NULL; } void * customer(void * arg) { while(1) { pthread_mutex_lock(&mutex); //儲存頭結點的指標 struct Node * tmp =head; if(head != NULL) { //有資料 head = head ->next; printf("del node num : %d, tid : %ld\n",tmp->num,pthread_self()); free(tmp); pthread_mutex_lock(&mutex); usleep(100); }else { pthread_mutex_unlock(&mutex); } } return NULL; } int main() { pthread_mutex_init(&mutex,NULL); //建立5個生產者執行緒,5個消費者執行緒 pthread_t ptids[5],ctids[5]; for(int i =0;i<5;i++) { pthread_create(&ptids[i],NULL,producer,NULL); pthread_create(&ctids[i],NULL,customer,NULL); } for(int i =0;i<5;i++) { pthread_detach(ptids[i]); pthread_detach(ctids[i]); } while(1) { sleep(10); } pthread_exit(NULL); pthread_mutex_destroy(&mutex); return 0; }
條件變數
產生錯誤後檢視錯誤,可生成core檔案
ulimit -c unlimited
gdb prodcust 檢視錯誤
條件變數輔助互斥量完成執行緒同步
◼ 條件變數的型別 pthread_cond_t ◼ int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); ◼ int pthread_cond_destroy(pthread_cond_t *cond); ◼ int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); ◼ int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); ◼ int pthread_cond_signal(pthread_cond_t *cond); ◼ int pthread_cond_broadcast(pthread_cond_t *cond);
//加條件變數的生產者消費者模型 /* 條件變數的型別 pthread_cond_t int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr); int pthread_cond_destroy(pthread_cond_t *cond); int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex); - 等待,呼叫了該函式,執行緒會阻塞。 int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime); - 等待多長時間,呼叫了這個函式,執行緒會阻塞,直到指定的時間結束。 int pthread_cond_signal(pthread_cond_t *cond); - 喚醒一個或者多個等待的執行緒 int pthread_cond_broadcast(pthread_cond_t *cond); - 喚醒所有的等待的執行緒 */ #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <unistd.h> // 建立一個互斥量 pthread_mutex_t mutex; // 建立條件變數 pthread_cond_t cond; struct Node{ int num; struct Node *next; }; // 頭結點 struct Node * head = NULL; void * producer(void * arg) { // 不斷的建立新的節點,新增到連結串列中 while(1) { pthread_mutex_lock(&mutex); struct Node * newNode = (struct Node *)malloc(sizeof(struct Node)); newNode->next = head; head = newNode; newNode->num = rand() % 1000; printf("add node, num : %d, tid : %ld\n", newNode->num, pthread_self()); // 只要生產了一個,就通知消費者消費 pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); usleep(100); } return NULL; } void * customer(void * arg) { while(1) { pthread_mutex_lock(&mutex); // 儲存頭結點的指標 struct Node * tmp = head; // 判斷是否有資料 if(head != NULL) { // 有資料 head = head->next; printf("del node, num : %d, tid : %ld\n", tmp->num, pthread_self()); free(tmp); pthread_mutex_unlock(&mutex); usleep(100); } else { // 沒有資料,需要等待 // 當這個函式呼叫阻塞的時候,會對互斥鎖進行解鎖,當不阻塞的,繼續向下執行,會重新加鎖。 pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); } } return NULL; } int main() { pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); // 建立5個生產者執行緒,和5個消費者執行緒 pthread_t ptids[5], ctids[5]; for(int i = 0; i < 5; i++) { pthread_create(&ptids[i], NULL, producer, NULL); pthread_create(&ctids[i], NULL, customer, NULL); } for(int i = 0; i < 5; i++) { pthread_detach(ptids[i]); pthread_detach(ctids[i]); } while(1) { sleep(10); } pthread_mutex_destroy(&mutex); pthread_cond_destroy(&cond); pthread_exit(NULL); return 0; }