#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<pthread.h>//static initialization, or use pthread_mutex_init() // and pthread_cond_init() at the beginning of main function
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t has_product = PTHREAD_COND_INITIALIZER;struct msg {int num;struct msg *next;};struct msg *head =NULL;struct msg *mp =NULL;void*producer(void*arg){for(;;){
mp =(struct msg *)malloc(sizeof(struct msg));if(mp ==NULL){perror("malloc error");exit(1);}
mp->num =rand()%100+1;//produces a productprintf("producer: %lu produces %d\n",pthread_self(), mp->num);pthread_mutex_lock(&mutex);//add a product to list(simulating the stack)
mp->next = head;
head = mp;pthread_mutex_unlock(&mutex);pthread_cond_signal(&has_product);//unblock at least one thread blocked on has_produtsleep(rand()%5);}}void*consumer(void*arg){for(;;){pthread_mutex_lock(&mutex);while(head ==NULL){//have no product yet; //can't replace while loop with if condition//'cause there can be more than one consumerpthread_cond_wait(&has_product,&mutex);//mutex is released and the thread is blocked // on condition variable has_product// until another thread calls pthread_cond_signal// or pthread_cond_broadcast//Upon successful return, the mutex shall have been locked// and shall be owned by the calling thread.}//delete a product from list(simulating the stack)
mp = head;
head = head->next;pthread_mutex_unlock(&mutex);printf("---consumer: %lu consumes %d---\n",pthread_self(), mp->num);free(mp);sleep(rand()%5);}}intmain(){srand(time(NULL));
pthread_t ptid, ctid;pthread_create(&ptid,NULL, producer,NULL);pthread_create(&ctid,NULL, consumer,NULL);pthread_join(ptid,NULL);pthread_join(ctid,NULL);pthread_mutex_destroy(&mutex);pthread_cond_destroy(&has_product);return0;}
线程或者进程阻塞时会释放所占用的cpu资源,提高效率
pthread_cond_timedwait函数中的第三个参数“绝对时间”的获取:
time_t cur =time(NULL);//获取当前绝对时间,相较于1970/1/1 00:00:00(Unix计时元年)struct timespec t;
t.tv_sec = cur +10;//10秒后pthread_cond_timedwait(&cond,&mutex,&t)
#include<stdio.h>#include<unistd.h>#include<semaphore.h>#include<stdlib.h>#include<pthread.h>#include<time.h>#define N 5
sem_t sem_blank;
sem_t sem_product;int num[N]={0};//circular queue implemented by global arrayvoid*producer(void*arg){int index =0;while(1){sem_wait(&sem_blank);//decrement sem_blank(if sem_blank is zero, block)
num[index]=rand()%10+1;//a product is producedprintf("produce--- %d\n", num[index]);sem_post(&sem_product);//increment sem_product and wake up threads blocked on sem_product(if any)
index =(index +1)% N;sleep(rand()%3);}pthread_exit((void*)1);}void*consumer(void*arg){int index =0;while(1){sem_wait(&sem_product);printf("---consume--- %d\n", num[index]);
num[index]=0;sem_post(&sem_blank);
index =(index +1)% N;sleep(rand()%3);}pthread_exit((void*)2);}intmain(){
pthread_t p_tid, c_tid1, c_tid2;srand(time(NULL));sem_init(&sem_product,0,0);sem_init(&sem_blank,0, N);pthread_create(&p_tid,NULL, producer,NULL);pthread_create(&c_tid1,NULL, consumer,NULL);pthread_create(&c_tid2,NULL, consumer,NULL);pthread_join(p_tid,NULL);pthread_join(c_tid1,NULL);pthread_join(c_tid2,NULL);sem_destroy(&sem_product);sem_destroy(&sem_blank);pthread_exit((void*)0);}