pthread_mutex_t qlock ;pthread_cond_t qready ;/************pthread_cond_wait()的使用方法**********/pthread_mutex_lock (& qlock ); /*lock*///等待某资源,并以qready作为条件通知我们pthread_cond_wait (& qready , & qlock ); /*block-->unlock-->wait() return-->lock*///do somethingpthread_mutex_unlock (& qlock ); /*unlock*//*****************************************************/
pthread_mutex_lock(&mtx);//这个mutex_lock主要是用来保护wait等待临界资源,//为何这里要有一个while (head == NULL)呢?//因为 如果有很多线程同时等待某资源, pthread_cond_wait里的线程可能会被意外唤醒,//那么这个时候仍然head == NULL,这就是“惊群效应”//这个时候,应该让线程继续进入pthread_cond_waitwhile (head == NULL)pthread_cond_wait(&cond, &mtx);// pthread_cond_wait会先解除之前的pthread_mutex_lock锁定的mtx//然后阻塞在等待队列里休眠,直到再次被唤醒//(大多数情况下是等待的条件成立而被唤醒)//唤醒后,该进程会先锁定先pthread_mutex_lock(&mtx); 再读取资源// 用这个流程是比较清楚的 /*block-->unlock-->wait() return-->lock*/
pthread_cond_signal在多处理器上可能同时唤醒多个线程,当你只能让一个线程处理某个任务时,其它被唤醒的线程就需要继续 wait, while循环的意义就体现在这里了,而且规范要求pthread_cond_signal至少唤醒一个pthread_cond_wait上的线程,其实有些实现为了简单在单处理器上也会唤醒多个线程.
某些应用,如
线程池,
pthread_cond_broadcast唤醒全部线程,但我们通常只需要一部分线程去做执行任务,所以
其它的线程需要继续wait.所以强烈推荐此处使用while循环. (惊群效应)
其实说白了很简单,就是pthread_cond_signal()也可能唤醒多个线程,而如果你同时只允许一个线程访问的话,就必须要使用while来进行条件判断,以保证临界区内只有一个线程在处理。
pthread_cond_signal函数的作用是发送一个信号给另外一个正在处于阻塞等待状态的线程,使其脱离阻塞状态,继续执行.如果没有线程处在阻塞等待状态,pthread_cond_signal也会成功返回。
用法:
pthread_cond_wait必须放在pthread_mutex_lock和pthread_mutex_unlock之间,因为他要根据共享变量的状态来决定是否要等待,而为了不永远等待下去所以必须要在lock/unlock队中。
共享变量的状态改变必须遵守lock/unlock的规则。
pthread_cond_signal既可以放在pthread_mutex_lock和pthread_mutex_unlock之间,也可以放在pthread_mutex_lock和pthread_mutex_unlock之后,但是各有各缺点。
之间:
pthread_mutex_lockxxxxxxxpthread_cond_signalpthread_mutex_unlock
缺点:在某下线程的实现中,会造成等待线程从内核中唤醒(由于cond_signal)然后又回到内核空间(因为cond_wait返回后会有原子加锁的行为),所以一来一回会有性能的问题。但是在LinuxThreads或者NPTL里面,就不会有这个问题,因为在Linux 线程中,有两个队列,分别是cond_wait队列和mutex_lock队列, cond_signal只是让线程从cond_wait队列移到mutex_lock队列,而不用返回到用户空间,不会有性能的损耗。
所以在Linux中推荐使用这种模式。
之后:
pthread_mutex_lock
xxxxxxx
pthread_mutex_unlock
pthread_cond_signal
优点:不会出现之前说的那个潜在的性能损耗,因为在signal之前就已经释放锁了
缺点:如果unlock和signal之前,有个低优先级的线程正在mutex上等待的话,那么这个低优先级的线程就会抢占高优先级的线程(cond_wait的线程),而这在上面的放中间的模式下是不会出现的。
所以,在Linux下最好pthread_cond_signal放中间,但从编程规则上说,其他两种都可以。