您好,登錄后才能下訂單哦!
死鎖產生的四個條件:
1、互斥使用(資源獨占)
一個資源每次只能給一個進程使用
.2、不可強占(不可剝奪)
資源申請者不能強行的從資源占有者手中奪取資源,資源只能由占有者自愿釋放
.3、請求和保持(部分分配,占有申請)
一個進程在申請新的資源的同時保持對原有資源的占有(只有這樣才是動態申請,動態分配)
.4、循環等待
存在一個進程等待隊列
{P1 , P2 , … , Pn},
其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個進程等待環路
生產者:生產數據
消費者:消費數據
提供場所:緩沖區,eg:超市
生產者消費者特點:三種關系,兩類人,一個場所
三種關系指的是:生產者與生產者之間是互斥關系
消費者與消費者之間是互斥關系
生產者與消費者之間是同步與互斥關系
兩類人:生產者,消費者
一個場所:存儲數據(此處用帶頭單鏈表實現)
單生產者單消費者模式:此例取數據方式為LIFO后進先出,所取數據為最后一個生產的數據(也可選擇所取數據為最先生產的數據,可自行選擇)
互斥鎖相關函數:
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);//非阻塞形式獲取鎖
int pthread_mutex_unlock(pthread_mutex_t *mutex);
//1.使用互斥鎖實現 #include<stdio.h> #include<malloc.h> #include<pthread.h> typedef int _dataType_; typedef int* _dataType_p_; typedef struct _node { _dataType_ data; struct _node* next; }node,*nodep,**nodepp; nodep head=NULL; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; nodep buyNode(_dataType_ val) { nodep tmp=(nodep)malloc(sizeof(node)); if(tmp!=NULL) { tmp->data=val; tmp->next=NULL; return tmp; } return NULL; } void init(nodepp head) { *head=buyNode(0); } void push_list(nodep head,_dataType_ val) { nodep tmp=buyNode(val); tmp->next=head->next; head->next=tmp; } int pop_list(nodep head,_dataType_p_ pval) { if(head->next==NULL) return -1; nodep del=head->next; *pval=del->data; head->next=del->next; free(del); return 0; } void* product(void* arg) { _dataType_ i=0; while(1) { sleep(1); pthread_mutex_lock(&mutex); push_list(head,i++); pthread_mutex_unlock(&mutex); } pthread_exit((void*)1); } void* consumer(void* arg) { _dataType_ val=0; while(1) { sleep(1); pthread_mutex_lock(&mutex); if(pop_list(head,&val)==-1) { pthread_mutex_unlock(&mutex); continue; } printf("data:%d\n",val); pthread_mutex_unlock(&mutex); } pthread_exit((void*)1); } int main() { pthread_t tid1,tid2; init(&head); pthread_create(&tid1,NULL,product,NULL); pthread_create(&tid2,NULL,consumer,NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); free(head); pthread_mutex_destroy(&mutex); return 0; }
//2.使用條件變量實現生產者消費者模式
條件變量:基于互斥鎖實現同步與互斥
一個條件變量總是和一個Mutex搭配使用。
一個線程可以調用pthread_cond_wait在一個Condition Variable上阻塞等待,這個函數做以下三步操作:
1. 釋放Mutex
2. 阻塞等待
3. 當被喚醒時,重新獲得Mutex并返回
條件變量相關函數:
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
pthread_cond_timedwait函數還有一個額外的參數可以設定等待超時,如果到達了abstime所指
定的時刻仍然沒有別的線程來喚醒當前線程,就返回ETIMEDOUT。
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
一個線程可以調用pthread_cond_signal喚醒在某個Condition Variable上等待的另一個線程,也可以調用pthread_cond_broadcast喚醒在這個Condition Variable上等待的所有線程。
#include<stdio.h> #include<malloc.h> #include<pthread.h> typedef int _dataType_; typedef int* _dataType_p_; typedef struct _node { _dataType_ data; struct _node* next; }node,*nodep,**nodepp; nodep head=NULL; pthread_cond_t cond=PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; nodep buyNode(_dataType_ val) { nodep tmp=(nodep)malloc(sizeof(node)); if(tmp!=NULL) { tmp->data=val; tmp->next=NULL; return tmp; } return NULL; } void init(nodepp head) { *head=buyNode(0); } void push_list(nodep head,_dataType_ val) { nodep tmp=buyNode(val); tmp->next=head->next; head->next=tmp; } int pop_list(nodep head,_dataType_p_ pval) { if(head->next==NULL) return -1; nodep del=head->next; *pval=del->data; head->next=del->next; free(del); return 0; } void* product(void* arg) { _dataType_ i=0; while(1) { sleep(1); pthread_mutex_lock(&mutex); push_list(head,i++); pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); } pthread_exit((void*)1); } void* consumer(void* arg) { _dataType_ val=0; while(1) { sleep(1); pthread_mutex_lock(&mutex); if(pop_list(head,&val)==-1) pthread_cond_wait(&cond,&mutex); printf("data:%d\n",val); pthread_mutex_unlock(&mutex); } pthread_exit((void*)1); } int main() { pthread_t tid1,tid2; init(&head); pthread_create(&tid1,NULL,product,NULL); pthread_create(&tid2,NULL,consumer,NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); free(head); pthread_cond_destroy(&cond); pthread_mutex_destroy(&mutex); return 0; }
//3.使用環形buf存儲數據,信號量的使用
信號量相關函數:
信號量(Semaphore)和Mutex類似,表示可用資源的數量,和Mutex不同的是這個數量可以大于1
#include <semaphore.h>
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_destroy(sem_t *sem);
int sem_wait(sem_t *sem);//類似P操作
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_post(sem_t *sem);//類似V操作
#include<stdio.h> #include<pthread.h> #include<semaphore.h> #define _SEM_PRO_ 20 #define _SEM_COM_ 0 typedef int _dataType_; _dataType_ blank[_SEM_PRO_]; sem_t sem_product; sem_t sem_consumer; void* product(void* arg) { int index=0; int count=0; while(1) { sleep(rand()%5); sem_wait(&sem_product); blank[index++]=count++; sem_post(&sem_consumer); index%=_SEM_PRO_; } pthread_exit((void*)1); } void* consumer(void* arg) { int index=0; while(1) { sem_wait(&sem_consumer); printf("data:%d\n",blank[index++]); sem_post(&sem_product); index%=_SEM_PRO_; } pthread_exit((void*)1); } int main() { pthread_t tid1,tid2; sem_init(&sem_product,0,20); sem_init(&sem_consumer,0,0); pthread_create(&tid1,NULL,product,NULL); pthread_create(&tid2,NULL,consumer,NULL); pthread_join(tid1,NULL); pthread_join(tid2,NULL); sem_destroy(&sem_product); sem_destroy(&sem_consumer); return 0; }
//4.多生產者,多消費者模式
#include<stdio.h> #include<pthread.h> #include<semaphore.h> #define _SEM_PRO_ 20 #define _SEM_COM_ 0 typedef int _dataType_; _dataType_ blank[_SEM_PRO_]; sem_t sem_product; sem_t sem_consumer; pthread_mutex_t mutex_product=PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t mutex_consumer=PTHREAD_MUTEX_INITIALIZER; void* product(void* arg) { int index=0; int count=0; while(1) { sleep(rand()%5); sem_wait(&sem_product); pthread_mutex_lock(&mutex_product); printf("%d thread id doing\n",(int)arg); blank[index++]=count++; index%=_SEM_PRO_; pthread_mutex_unlock(&mutex_product); sem_post(&sem_consumer); } pthread_exit((void*)1); } void* consumer(void* arg) { int index=0; while(1) { sem_wait(&sem_consumer); pthread_mutex_lock(&mutex_consumer); printf("%d thread is consumer,data:%d\n",(int)arg,blank[index++]); index%=_SEM_PRO_; pthread_mutex_unlock(&mutex_consumer); sem_post(&sem_product); } pthread_exit((void*)1); } int main() { pthread_t tid1,tid2,tid3,tid4; sem_init(&sem_product,0,20); sem_init(&sem_consumer,0,0); pthread_create(&tid1,NULL,product,(void*)1); pthread_create(&tid2,NULL,consumer,(void*)2); pthread_create(&tid3,NULL,product,(void*)3); pthread_create(&tid4,NULL,consumer,(void*)4); pthread_join(tid1,NULL); pthread_join(tid2,NULL); pthread_join(tid3,NULL); pthread_join(tid4,NULL); sem_destroy(&sem_product); sem_destroy(&sem_consumer); pthread_mutex_destroy(&mutex_product); pthread_mutex_destroy(&mutex_consumer); }
運行結果顯示:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。