Linux 多线程条件变量同步(2)

OK,这个就是pthread_cond_wait()的原理了,只不过它把continue变成了"休眠"这种由OS负责的操作,可以大大的节约资源。
当然,线程执行的条件是很难当作参数传入一个函数的,POSIX多线程的模型使用系统提供的"条件变量"+"我们自己定义的具体条件" 来确定一个线程是否应该执行接下来的内容。"条件变量"只有,所以一种典型的多线程同步的结构如下

//线程B,出队 while(1){ lock(mutex); while(条件不满足) pthread_cond_wait(cond,mutex) //获得互斥锁可以同时保护while里的条件和cond的判断,二者总是用一把锁保护,并一同释放 //cond为假,就休眠同时释放锁,等待被cond为真唤醒,把自己获得的锁拿回来 //拿回自己的锁再检查线程执行条件,条件不满足继续循环,直到条件满足跳出循环 //这个函数是带着"线程的执行条件为真"+"cond为真"走出循环的 //这个函数返回后cond被重新设置为0 out_queue(Q); unlock(mutex); } pthread_cond_braoadcast()/pthread_cond_signal() //使条件变量为真并唤醒wait中的线程,前者唤醒所有wait的,后者唤醒一个 //成功返回0,失败返回error number int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_signal(pthread_cond_t *cond); pthread_cond_destroy() //销毁条件变量 //成功返回0,失败返回error number int pthread_cond_destroy(pthread_cond_t *cond); 例子-线程池 \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ //thread.h #ifndef __THREAD_H__ #define __THREAD_H__ #define THREAD_NUM 3 #define TASK_NUM 100 typedef struct{//每个节点的封装格式,fcn是用户自定义函数,arg是用户自定义函数参数指针,保证通用性声明为void void* (*fcn)(void* arg); void* arg; }task_t; typedef struct{ //用户自定义函数的参数结构体 int x; }argfcn_t; //#define LQ_DATA_T task_t* #define LQ_DATA_T task_t #endif //__THREAD_H__ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ //lqueue.c #include"thread.h" #include"lqueue.h" #include<stdlib.h> ... \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ //thread_pool.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include<pthread.h> #include"thread.h" #include"lqueue.h" //互斥量和条件变量 pthread_mutex_t lock; pthread_cond_t cond; //全局的表 lqueue_t* Q; //每个线程的任务,必须是这个形式的函数指针 void* do_task(void* p){ task_t data; int ret=0; while(1){ pthread_mutex_lock(&lock); while(is_empty_lqueue(Q)){ //大家收到广播,因为延迟,可能醒了好几个,要判断一下是不是自己 pthread_cond_wait(&cond,&lock); //先抢到锁再醒 } ret=out_lqueue(Q,&data); pthread_mutex_unlock(&lock); data.fcn(data.arg); } } //创建线程池 void create_pool(void){ //初始化队列 Q=create_lqueue(); //初始化互斥量 pthread_mutex_init(&lock,NULL); //初始化条件变量 pthread_cond_init(&cond,NULL); int i=THREAD_NUM; pthread_t tid[THREAD_NUM]; while(i--) pthread_create(&tid[i],NULL,do_task,NULL); } //准备函数 void* fcn(void* parg){ //用户自定义的需要线程执行的函数 argfcn_t* i=(argfcn_t*)parg; printf("this is task1\n"); printf("task1:%d\n",i->x); } //添加任务 void pool_add_task(void*(*pfcn)(void*parg),void*arg){ task_t task; task.fcn=pfcn; task.arg=arg; in_lqueue(Q,task); pthread_cond_signal(&cond); //添加了一个任务,用signal更好 } int main(int argc, const char *argv[]) { //创建线程池 create_pool(); //准备参数 argfcn_t argfcn; argfcn.x=5; //添加任务 pool_add_task(fcn,(void*)&argfcn); pool_add_task(fcn,(void*)&argfcn); pool_add_task(fcn,(void*)&argfcn); pause(); return 0; }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/14799.html