条件变量:与互斥量一起使用,暂时申请不到某资源时进入条件阻塞等待,当资源具备时线程恢复运行
应用场合:生产线程不断的生产资源,并通知产生资源的条件,消费线程在没有资源情况下进入条件等待,一直等到条件信号的产生
主要函数有两个:
1)等待条件
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
2)发送条件信号
int pthread_cond_signal(pthread_cond_t *cond);
请参考:
http://www.diybl.com/course/3_program/c++/cppjs/20110518/555794.html
http://www.ibm.com/developerworks/cn/linux/thread/posix_threadapi/part3/
编译:
gcc -o pthread pthread.c -lpthread
/*单个生产者和单个消费者*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include <pthread.h> #define BUFFER_SIZE 5 //产品库存大小 #define PRODUCT_CNT 50 //产品生产总数 struct product_cons { int buffer[BUFFER_SIZE]; //生产产品值 pthread_mutex_t lock; //互斥锁 volatile int int readpos, writepos; //读写位置 pthread_cond_t notempty; //条件变量,非空 pthread_cond_t notfull; //非满 }buffer; void init(struct product_cons *p) { pthread_mutex_init(&p->lock, NULL); //互斥锁 pthread_cond_init(&p->notempty, NULL); //条件变量 pthread_cond_init(&p->notfull, NULL); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; } void fini(struct product_cons *p) { pthread_mutex_destroy(&p->lock); //互斥锁 pthread_cond_destroy(&p->notempty); //条件变量 pthread_cond_destroy(&p->notfull); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; } void cleanup_handler(void *arg) { printf("cleanup_handler exec!\n"); pthread_mutex_t *lock = (pthread_mutex_t*)arg; pthread_mutex_unlock(lock); //解锁 } //存储 一个数据 到 bufferr void put(struct product_cons *p, int data) //输入产品子函数 { pthread_mutex_lock(&p->lock); //上锁 /*等待,直到 buffer 不为 满*/ while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满 { printf("producer wait for not full\n"); pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待 //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号 //如果,消费者发送了 signal 信号,表示有了 空闲 } p->buffer[p->writepos] = data; //写数据 p->writepos++; if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回 p->writepos = 0; pthread_cond_signal(&p->notempty); //发送有数据信号 pthread_mutex_unlock(&p->lock); //解锁 } //读,移除 一个数据 从 buffer int get(struct product_cons *p) { int data = 0; pthread_mutex_lock(&p->lock); /*等待,直到不为空*/ while(p->writepos == p->readpos) { printf("consumer wait for not empty\n"); pthread_cond_wait(&p->notempty,&p->lock); } /*读 一个 数据*/ data = p->buffer[p->readpos]; p->readpos++; if(p->readpos >= BUFFER_SIZE) //如果读到 尾 p->readpos = 0; pthread_cond_signal(&p->notfull); pthread_mutex_unlock(&p->lock); return data; } void *producer(void *data) //子线程 ,生产 { int n; for(n = 1; n <= 50; ++n) //生产 50 个产品 { sleep(1); printf("put the %d product\n",n); put(&buffer,n); } printf("producer stopped\n"); return NULL; } void *consumer(void *data) { static int cnt = 0; while(1) { sleep(2); printf("get the %d product\n", get(&buffer)); if(++cnt == PRODUCT_CNT) 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); fini(&buffer); return 0; }
/*多个生产者和单个消费者*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include <pthread.h> #define BUFFER_SIZE 5 //产品库存大小 #define PRODUCT_CNT 50 //产品生产总数 struct product_cons { int buffer[BUFFER_SIZE]; //生产产品值 pthread_mutex_t lock; //互斥锁,控制buffer int readpos, writepos; //读写位置 pthread_cond_t notempty; //条件变量,非空 pthread_cond_t notfull; //非满 pthread_mutex_t lock2; //互斥锁,控制cnt int cnt; //完成生产产品数量 }buffer; void init(struct product_cons *p) { pthread_mutex_init(&p->lock, NULL); //互斥锁 pthread_cond_init(&p->notempty, NULL); //条件变量 pthread_cond_init(&p->notfull, NULL); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; pthread_mutex_init(&p->lock2, NULL); p->cnt = 0; } void fini(struct product_cons *p) { pthread_mutex_destroy(&p->lock); //互斥锁 pthread_cond_destroy(&p->notempty); //条件变量 pthread_cond_destroy(&p->notfull); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; pthread_mutex_destroy(&p->lock2); p->cnt = 0; } //存储 一个数据 到 bufferr void put(struct product_cons *p, int data) //输入产品子函数 { pthread_mutex_lock(&p->lock); //上锁 /*等待,直到 buffer 不为 满*/ while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满 { printf("producer wait for not full\n"); pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待 //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号 //如果,消费者发送了 signal 信号,表示有了 空闲 } p->buffer[p->writepos] = data; //写数据 p->writepos++; if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回 p->writepos = 0; pthread_cond_signal(&p->notempty); //发送有数据信号 pthread_mutex_unlock(&p->lock); //解锁 } //读,移除 一个数据 从 buffer int get(struct product_cons *p) { int data = 0; pthread_mutex_lock(&p->lock); /*等待,直到不为空*/ while(p->writepos == p->readpos) { printf("consumer wait for not empty\n"); pthread_cond_wait(&p->notempty,&p->lock); } /*读 一个 数据*/ data = p->buffer[p->readpos]; p->readpos++; if(p->readpos >= BUFFER_SIZE) //如果读到 尾 p->readpos = 0; pthread_cond_signal(&p->notfull); pthread_mutex_unlock(&p->lock); return data; } void *producer(void *data) //子线程 ,生产 { int flag = -1; while(1) { pthread_mutex_lock(&buffer.lock2); if(buffer.cnt < PRODUCT_CNT) { ++buffer.cnt; printf("%s put the %d product\n", (char*)data, buffer.cnt); put(&buffer, buffer.cnt); } else flag = 0; pthread_mutex_unlock(&buffer.lock2); if(!flag) break; sleep(2); } printf("%s producer stopped\n", (char*)data); return NULL; } void *consumer(void *data) { int d = 0; while(1) { sleep(1); d = get(&buffer); printf("get the %d product\n",d); if(d == PRODUCT_CNT) break; } printf("consumer stopped\n"); return NULL; } int main(int argc, char *argv[]) { pthread_t th_a[3],th_b; void *retval; init(&buffer); pthread_create(&th_a[0], NULL, producer, (void*)"th_a[0]"); pthread_create(&th_a[1], NULL, producer, (void*)"th_a[1]"); pthread_create(&th_a[2], NULL, producer, (void*)"th_a[2]"); pthread_create(&th_b, NULL, consumer, 0); pthread_join(th_a[0], &retval); pthread_join(th_a[1], &retval); pthread_join(th_a[2], &retval); pthread_join(th_b, &retval); fini(&buffer); return 0; }
/*单个生产者和多个消费者*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include <pthread.h> #define BUFFER_SIZE 5 //产品库存大小 #define PRODUCT_CNT 50 //产品生产总数 struct product_cons { int buffer[BUFFER_SIZE]; //生产产品值 pthread_mutex_t lock; //互斥锁 volatile int int readpos, writepos; //读写位置 pthread_cond_t notempty; //条件变量,非空 pthread_cond_t notfull; //非满 pthread_mutex_t lock2; //互斥锁,控制cnt int cnt; //获得生产产品数量 }buffer; void init(struct product_cons *p) { pthread_mutex_init(&p->lock, NULL); //互斥锁 pthread_cond_init(&p->notempty, NULL); //条件变量 pthread_cond_init(&p->notfull, NULL); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; pthread_mutex_init(&p->lock2, NULL); p->cnt = 0; } void fini(struct product_cons *p) { pthread_mutex_destroy(&p->lock); //互斥锁 pthread_cond_destroy(&p->notempty); //条件变量 pthread_cond_destroy(&p->notfull); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; pthread_mutex_destroy(&p->lock2); p->cnt = 0; } //存储 一个数据 到 bufferr void put(struct product_cons *p, int data) //输入产品子函数 { pthread_mutex_lock(&p->lock); //上锁 /*等待,直到 buffer 不为 满*/ while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满 { printf("producer wait for not full\n"); pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待 //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号 //如果,消费者发送了 signal 信号,表示有了 空闲 } p->buffer[p->writepos] = data; //写数据 p->writepos++; if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回 p->writepos = 0; pthread_cond_signal(&p->notempty); //发送有数据信号 pthread_mutex_unlock(&p->lock); //解锁 } //读,移除 一个数据 从 buffer int get(struct product_cons *p) { int data = 0; pthread_mutex_lock(&p->lock); /*等待,直到不为空*/ while(p->writepos == p->readpos) { printf("consumer wait for not empty\n"); pthread_cond_wait(&p->notempty,&p->lock); } /*读 一个 数据*/ data = p->buffer[p->readpos]; p->readpos++; if(p->readpos >= BUFFER_SIZE) //如果读到 尾 p->readpos = 0; pthread_cond_signal(&p->notfull); pthread_mutex_unlock(&p->lock); return data; } void *producer(void *data) //子线程 ,生产 { int n; for(n = 1; n <= PRODUCT_CNT; ++n) //生产 50 个产品 { sleep(1); printf("put the %d product\n",n); put(&buffer, n); } printf("producer stopped\n"); return NULL; } void *consumer(void *data) { int flag = -1; while(1) { pthread_mutex_lock(&buffer.lock2); if(buffer.cnt < PRODUCT_CNT) { printf("%s get the %d product\n", (char*)data, get(&buffer)); ++buffer.cnt; } else flag = 0; pthread_mutex_unlock(&buffer.lock2); if(!flag) break; sleep(2); } printf("%s consumer stopped\n", (char*)data); return NULL; } int main(int argc, char *argv[]) { pthread_t th_a,th_b[3]; void *retval; init(&buffer); pthread_create(&th_a, NULL, producer, 0); pthread_create(&th_b[0], NULL, consumer, (void*)"th_b[0]"); pthread_create(&th_b[1], NULL, consumer, (void*)"th_b[1]"); pthread_create(&th_b[2], NULL, consumer, (void*)"th_b[2]"); pthread_join(th_a, &retval); pthread_join(th_b[0], &retval); pthread_join(th_b[1], &retval); pthread_join(th_b[2], &retval); fini(&buffer); return 0; }
/*多个生产者和多个消费者*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include <pthread.h> #define BUFFER_SIZE 5 //产品库存大小 #define PRODUCT_CNT 50 //产品生产总数 struct product_cons { int buffer[BUFFER_SIZE]; //生产产品值 pthread_mutex_t lock; //互斥锁 volatile int int readpos, writepos; //读写位置 pthread_cond_t notempty; //条件变量,非空 pthread_cond_t notfull; //非满 pthread_mutex_t lock2; //互斥锁,控制cnt_p int cnt_p; //完成生产产品数量 pthread_mutex_t lock3; //互斥锁,控制cnt_c int cnt_c; //获得生产产品数量 }buffer; void init(struct product_cons *p) { pthread_mutex_init(&p->lock, NULL); //互斥锁 pthread_cond_init(&p->notempty, NULL); //条件变量 pthread_cond_init(&p->notfull, NULL); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; pthread_mutex_init(&p->lock2, NULL); p->cnt_p = 0; pthread_mutex_init(&p->lock3, NULL); p->cnt_c = 0; } void fini(struct product_cons *p) { pthread_mutex_destroy(&p->lock); //互斥锁 pthread_cond_destroy(&p->notempty); //条件变量 pthread_cond_destroy(&p->notfull); //条件变量 p->readpos = 0; //读写位置 p->writepos = 0; pthread_mutex_destroy(&p->lock2); p->cnt_p = 0; pthread_mutex_destroy(&p->lock3); p->cnt_c = 0; } //存储 一个数据 到 bufferr void put(struct product_cons *p, int data) //输入产品子函数 { pthread_mutex_lock(&p->lock); //上锁 /*等待,直到 buffer 不为 满*/ while((p->writepos + 1) % BUFFER_SIZE == p->readpos) //测试空间是否已满 { printf("producer wait for not full\n"); pthread_cond_wait(&p->notfull, &p->lock); //阻塞等待 //这里,生产者 notfull 等待消费者 pthread_cond_signal(&p->notfull);信号 //如果,消费者发送了 signal 信号,表示有了 空闲 } p->buffer[p->writepos] = data; //写数据 p->writepos++; if(p->writepos >= BUFFER_SIZE) //如果写到 尾部,返回 p->writepos = 0; pthread_cond_signal(&p->notempty); //发送有数据信号 pthread_mutex_unlock(&p->lock); //解锁 } //读,移除 一个数据 从 buffer int get(struct product_cons *p) { int data = 0; pthread_mutex_lock(&p->lock); /*等待,直到不为空*/ while(p->writepos == p->readpos) { printf("consumer wait for not empty\n"); pthread_cond_wait(&p->notempty,&p->lock); } /*读 一个 数据*/ data = p->buffer[p->readpos]; p->readpos++; if(p->readpos >= BUFFER_SIZE) //如果读到 尾 p->readpos = 0; pthread_cond_signal(&p->notfull); pthread_mutex_unlock(&p->lock); return data; } void *producer(void *data) //子线程 ,生产 { int flag = -1; while(1) { pthread_mutex_lock(&buffer.lock2); if(buffer.cnt_p < PRODUCT_CNT) { ++buffer.cnt_p; printf("%s put the %d product\n", (char*)data, buffer.cnt_p); put(&buffer, buffer.cnt_p); } else flag = 0; pthread_mutex_unlock(&buffer.lock2); if(!flag) break; sleep(2); } printf("%s producer stopped\n", (char*)data); return NULL; } void *consumer(void *data) { int flag = -1; while(1) { pthread_mutex_lock(&buffer.lock3); if(buffer.cnt_c < PRODUCT_CNT) { printf("%s get the %d product\n", (char*)data, get(&buffer)); ++buffer.cnt_c; } else flag = 0; pthread_mutex_unlock(&buffer.lock3); if(!flag) break; sleep(2); } printf("%s consumer stopped\n", (char*)data); return NULL; } int main(int argc, char *argv[]) { pthread_t th_a[3],th_b[3]; void *retval; init(&buffer); pthread_create(&th_a[0], NULL, producer, (void*)"th_a[0]"); pthread_create(&th_a[1], NULL, producer, (void*)"th_a[1]"); pthread_create(&th_a[2], NULL, producer, (void*)"th_a[2]"); pthread_create(&th_b[0], NULL, consumer, (void*)"th_b[0]"); pthread_create(&th_b[1], NULL, consumer, (void*)"th_b[1]"); pthread_create(&th_b[2], NULL, consumer, (void*)"th_b[2]"); pthread_join(th_a[0], &retval); pthread_join(th_a[1], &retval); pthread_join(th_a[2], &retval); pthread_join(th_b[0], &retval); pthread_join(th_b[1], &retval); pthread_join(th_b[2], &retval); fini(&buffer); return 0; }