您的位置:首页 > 其它

pthread几个互斥锁和条件变量接口

2016-04-16 17:46 357 查看
pthread_cleanup_push/pthread_cleanup_pop:pthread_cleanup_push(pthread_mutex_unlock, (void *) &mut);  //可以注册pthread_mutex_unlock,也可以注册自定义的函数pthread_mutex_lock(&mut);//do something。此过程中假如本线程做某些事时异常退出,或者被别的线程cancel,那么mut就永远得不到执行pthread_mutex_unlock(&mut);pthread_cleanup_pop(0);pthread_cond_wait(&cond, &mut):内部顺序执行pthread_mutex_unlock(&mut),pthread_cond_just_wait(&cond),pthread_mutex_lock(&mut),其中,前两个函数(unlock和just_wait)必须从语义上原子化。如果不原子化,会出现unlock之后别的线程获得mut,然后发送signal/broadcast,最后本线程调用just_wait。也就是说just_wait发生在signal/broadcast之前,所以本线程永远不会得到唤醒。对于同一个cond,必须用同一个mut来配合使用。使用示例如下:
pthread_mutex_lock(&mut);while(flag!=true)                //如果flag不为true,我们调cond_wait把自己给阻塞了pthread_cond_wait(&cond,&mut); //前后必须要加互斥锁,而pthread_cond_signal前后则无所谓加不加互斥锁pthread_mutex_unlock(&mut);
pthread_cond_wait()前后必须加互斥锁,是为了保证对条件flag的互斥访问,如果不加互斥锁,可能出现如下情况:
thread1:                      thread2:while(flag!=true)                                     //flag==falseflag=true;              //flag==truepthread_cond_wait();                                  //thread1已进入阻塞状态,但其实此时flag是为true的,即漏过了这个条件了..........
另外,pthread_cond_wait(&cond,&mut)内部大致包含下面几个步骤:1、进入wait,处理条件变量,2、解锁mut;3、把自己给阻塞了;4、睡眠;5、睡眠;6、。。。7、收到别的线程通知(pthread_cond_signal/broadcast)可以醒了;8、醒来;9、尝试锁定mut,如果成功则函数返回;10、不成功的话阻塞并等待mut可用。以上步骤,可以由下图(来自pthread条件变量condition(配合mutex锁使用),经典,有图)描述:此外,注意如果有多个线程在等待条件变量时,需要用while(flag!=true),在wait返回的时候再判断一次flag。原因是wait执行时可能存在下面的场景(signal/broadcast惊群,线程1和线程3同时收到信号):
线程1                                                           线程31、收到别的线程通知(pthread_cond_signal/broadcast)可以醒了;    1、收到别的线程通知(pthread_cond_signal/broadcast)可以醒了;2、尝试加锁mut失败;                                            2、成功锁定mut;3、睡眠                                                         3、置flag为false;4、睡眠                                                         4、解锁mut;5、成功锁定mut;6、wait函数返回,线程醒来。
线程1醒来后必须再判断flag,flag可能为false了,因为线程1加锁mut失败的时候flag被别的线程修改了。pthread_cond_signal():有两种用法,都可以:用法1:                                                                                                        用法2:pthread_mutex_lock(&mut);                                                                     pthread_mutex_lock(&mut);atomic_i++;                                                                                                  atomic_i++;pthread_cond_signal(&cond);                                                                 pthread_mutex_unlock(&mut);pthread_mutex_unlock(&mut);                                                                pthread_cond_signal(&cond);两种用法各有优缺点:用法1在某些OS的实现中,可能会造成signal之后还没unlock,但是另一个收到cond的线程在cond_wait()中最后试图lock,lock失败,导致重新陷入内核态,直到本线程unlock,由此带来性能损失。用法2会出现unlock之后signal之前有别的低优先级线程抢占了mut,导致更高优先级的等待cond_wait的线程被低优先级线程抢占。用法1在Linux下不会有上面提到的缺点,因为在Linux中,cond_signal只会让线程从cond_wait队列移到mutex_lock队列。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: