【linux高级程序设计】(第十二章)Linux多线程编程 3
条件变量通信机制
条件变量必须配合互斥锁一起实现对资源的互斥访问
使用方法:
int pthread_cond_init (pthread_cond_t *__restrict __cond, __const pthread_condattr_t *__restrict __cond_attr) :初始化条件变量,第二个参数是属性对象,NULL为默认
int pthread_cond_destroy (pthread_cond_t *__cond) :销毁条件变量
int pthread_cond_signal (pthread_cond_t *__cond) :通知等待条件变量的第一个线程,如果没有等待线程,则不起作用
int pthread_cond_broadcast (pthread_cond_t *__cond) :通知等待的条件变量的所有线程,如果没有等待线程,则不起作用
int pthread_cond_wait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex) :等待条件变量,第二个参数指向于条件变量关联的互斥锁指针
int pthread_cond_timewait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex, __const struct timespec *__restrict __abstime) :在指定时间内等待条件变量。
在线程因等待条件变量进入等待状态时,将释放其申请的互斥锁。在等到条件变量时,会隐含申请到该互斥锁
条件变量实现读写锁
#include<stdio.h> #include<stdlib.h> #include<time.h> #include "pthread.h" #define BUFFER_SIZE 2 //条件信息结构体 struct prodcons { int buffer[BUFFER_SIZE]; //生产产品值 pthread_mutex_t lock; //互斥锁 int readpos, writepos; //读写位置 pthread_cond_t notempty; //条件变量,表非空 pthread_cond_t notfull; //条件变量,表非满 }; //初始化 void init(struct prodcons *prod) { pthread_mutex_init(&prod->lock, NULL); pthread_cond_init(&prod->notempty, NULL); pthread_cond_init(&prod->notfull, NULL); prod->readpos = 0; prod->writepos = 0; } //在缓冲区输入一个数据 void put(struct prodcons * prod, int data) { //锁定互斥锁 pthread_mutex_lock(&prod->lock); while((prod->writepos + 1) % BUFFER_SIZE == prod->readpos) //测试是否空间已满 注意 这里writepos的位置要加1 即保证下一个写入的位置是空的 ?? { printf("producer wait for not full\n"); pthread_cond_wait(&prod->notfull, &prod->lock); //等待有空间写 } //写数据 prod->buffer[prod->writepos] = data; prod->writepos++; if(prod->writepos >= BUFFER_SIZE) prod->writepos = 0; pthread_cond_signal(&prod->notempty); pthread_mutex_unlock(&prod->lock); } //从缓冲区读一个数据 int get(struct prodcons * prod) { int data; //锁定互斥锁 pthread_mutex_lock(&prod->lock); while(prod->writepos == prod->readpos) { printf("producer wait for not empty\n"); pthread_cond_wait(&prod->notempty, &prod->lock); } data = prod->buffer[prod->readpos]; prod->readpos++; if(prod->readpos >= BUFFER_SIZE) prod->readpos = 0; pthread_cond_signal(&prod->notfull); pthread_mutex_unlock(&prod->lock); return data; } #define OVER (-1) struct prodcons buffer; //生产者 void * producer(void * data) { int n; for(n = 1; n <= 5; n++) //生产5个产品 { printf("producer sleep 1 second...\n"); sleep(1); printf("put the %d product\n", n); put(&buffer, n); } for(n = 6; n <= 10; n++) { printf("producer sleep 3 second...\n"); sleep(3); printf("put the %d product\n", n); put(&buffer, n); } put(&buffer, OVER); printf("producer stopped!\n"); return NULL; } //消费者 void * consumer(void * data) { int d = 0; while(1) { printf("consumer sleep 2 second...\n"); sleep(2); d = get(&buffer); printf("get the %d product\n", d); if(d == OVER) break; } printf("consumer stopped!\n"); return NULL; } int main(int argc, char *argv[]) { pthread_t th_a, th_b; void * retval; init(&buffer); pthread_create(&th_a, NULL, producer, 0); pthread_create(&th_b, NULL, consumer, 0); pthread_join(th_a, &retval); pthread_join(th_b, &retval); return 0; }
验证,可用