【C语言】【unix c】条件变量线程同步

来源:互联网 发布:电子商务系统代码java 编辑:程序博客网 时间:2024/06/05 05:12
    什么是条件变量?        线程a等待某个条件成立,条件成立,线程a才继续向下执行。线程b的执行使条件成立,条件成立之后唤醒线程a,以继续执行。这个条件就是条件变量        pthread_cond_t 就是条件变量类型    对类型的封装如下:        #include <pthread.h>        pthread_cond_t cond = PTHREAD_COND_INITIALIZER; //条件变量的静态初始化,定义变量可以用        int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);            功能:初始化一个条件变量            参数:                cond:指定要初始化的条件变量(指向结构pthread_cond_t的指针)                cond_attr:NULL 默认的(用于设置条件变量是进程内还是进程间的)            返回值:0 成功                    非0 错误       int pthread_cond_signal(pthread_cond_t *cond);            功能:启动在等待条件变量变为真的一个线程,每次最多可以给一个线程发送            参数:                cond:指定条件变量            返回值:0 成功                 非0 错误       int pthread_cond_broadcast(pthread_cond_t *cond);            功能:启动所有的等待条件变量为真的线程            参数:                cond:指定条件变量            返回值:0 成功                    非0 错误       int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);  //等待期间不会占用cpu,先解锁,然后进入睡眠状态,等待接受信号            功能:等待条件变量为真(无条件等待)            参数:                cond:指定等待的条件变量                mutex:等待之前需要解开的锁            返回值:0 成功                    非0 错误       int   pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex, const struct timespec *abstime); //超时等待            功能:超时等待,超时返回错误(计时等待)            参数:                cond:指定等待的条件变量                mutex:等待之前需要解开的锁                abstime:指定等待的时间            返回值:0 成功                    非0 错误       int pthread_cond_destroy(pthread_cond_t *cond);            功能:销毁一个条件变量            参数:                cound:指定要销毁的条件变量            返回值:0 成功                    非0 错误    操作步骤:        1、解开mutex锁        2、让线程等待条件变量为真        3、条件变量为真时加锁    生产者和消费者(读者和写者)    链表实现:生产者生产出来对象,放到链表头部,消费者从链表的头部取出消费    第一个思考:两个线程如何同步访问链表的头部    第二个思考:如果链表为空,消费者等待生产者生产对象    第三个思考:生产者线程生产出对象需要通知消费者        代码见 cond.c        #include <stdio.h>        #include <pthread.h>        #include <stdlib.h>        #include <time.h>        typedef struct node{            int num;            struct node  *next;        }node_t;        typedef node_t *list_t;        list_t head=NULL;        pthread_mutex_t mutex=\                    PTHREAD_MUTEX_INITIALIZER;        pthread_cond_t cond=\                PTHREAD_COND_INITIALIZER;        //消费者线程        void *consume(void *arg){            node_t *tmp;            while(1){                //加锁                pthread_mutex_lock(&mutex);//对临界变量加锁                if(head==NULL)//如果头部指向空,等待                    pthread_cond_wait(&cond,&mutex);                tmp=head;//将要删除的节点赋值给中间值,然后头指针指向下一个                head=head->next;//                //解锁                pthread_mutex_unlock(&mutex);                //消费tmp节点                printf("consum:%d\n",tmp->num);                free(tmp);                tmp=NULL;                sleep(rand()%5);            }        }        //生产者线程        void *product(void *arg){//函数的格式void *(*start_routine) (void *),返回值是指针,参数也是            node_t *n;            while(1){                //生产一个新的节点                n=(node_t *)malloc(sizeof(node_t));                n->num=rand()%1000+1;                printf("p:%d\n",n->num);            //加锁                pthread_mutex_lock(&mutex);                //将新节点放入到链表的头部                n->next=head;                head=n;            //解锁                pthread_mutex_unlock(&mutex);                //通知消费者                pthread_cond_signal(&cond);                sleep(rand()%5);            }        }        int main(void){            pthread_t pid,cid;            //设置随机数的种子            srand(time(NULL));            //创建两个线程,用于生产者和消费者            pthread_create(&pid,NULL,product,NULL);//创建线程后即执行该线程            pthread_create(&cid,NULL,consume,NULL);//参数含义是(存放ID的缓存区,NULL缺省属性,线程的执行函数,函数的唯一参数)            //等待线程的汇合            pthread_join(pid,NULL);            pthread_join(cid,NULL);            //销毁mutex锁            pthread_mutex_destroy(&mutex);            pthread_cond_destroy(&cond);            return 0;        }        tarena@ubuntu:~/day/day37$ gcc cond.c -lpthread        tarena@ubuntu:~/day/day37$ a.out         p:637        consum:637        p:741        consum:741        p:243        consum:243        p:651        consum:651        p:252        consum:252        p:244        p:612        p:954        p:627        p:564        consum:564        p:941        consum:941        p:347        consum:347        p:28        consum:28        p:60        p:174        consum:174        p:824        p:359        consum:359        consum:824        p:671        p:8        p:164        ^C    分析:链表会将之前没有出来的先压在下面,直到前面的输出完才会将他们输出来
原创粉丝点击