[多线程学习笔记]条件变量

关于条件变量这一节的知识几乎惹怒了我,不知道是原书就不好,还是翻译的不好,还是我笨的原因,总而言之就是看不懂。

现在说一下我的理解:

条件变量虽说是和某个谓词绑定,但是其实只是程序员的工作,并没有真正的绑定。

使用条件变量的场景是,一个队列空了,我们要等待它不为空,虽然也不知道谁规定的,大家都用while,而不用if

while(QUEUE_IS_EMPTY())

{

  pthread_cond_wait(&cond,&mutex);

}

/*************************************************************************
    > File Name: lifecycle.c
    > Author: likeyi
    > Mail: likeyiyy@sina.com 
    > Created Time: Thu 17 Apr 2014 11:00:08 AM CST
 ************************************************************************/
                    
#include <stdio.h> 
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond   = PTHREAD_COND_INITIALIZER;
int a,b;            
void * delay_print(void * arg)
{                   
    pthread_detach(pthread_self());
    sleep(1);       
    printf("Hello world\n");
    a = 7;          
    b = 8;          
    pthread_cond_signal(&cond);
                    
}                   
int main(int argc,char * argv[])
{                   
    pthread_t tid; 
    int result = pthread_create(&tid,NULL,delay_print,NULL);
    if(result != 0)
    {               
        printf("create thread error\n");
        exit(0);    
    }               
    printf("printf form main\n");
    a = 6;          
    b = 5;          
    if(a != b)      
    {               
        pthread_cond_wait(&cond,&mutex);
    }               
    printf("a= %d b = %d\n",a,b);
    pthread_exit(&result);
}  

如上面的代码所示,当a不等于b时我们就等待,从这个逻辑上来说我们是期望当a等于b的时候把我们唤醒。

然而事实上,这个绑定只是程序员的主观愿望,上面的代码,在子线程中我们让a=8,b=9,然后调用了pthread_cond_signal,仍然唤醒了主线程。

 

这是多么不好的语义啊,完全靠程序员自己来进行绑定啊。

有没有一种操作是原子的等待wait bool is 1

比如说atomic_wait(a==b),我希望有这样的函数。

 

/***********************************************************************************************************/

从上面的代码我们也能看出,之所以要用while而不用if的原因,书上讲了三个原因:

被拦截的唤醒,松散的唤醒,假唤醒。不知道假唤醒是不是我这样的假的唤醒。

总而言之:总是在while循环中测试谓词来等待条件变量。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond   = PTHREAD_COND_INITIALIZER;
int a,b;
void * delay_print(void * arg)
{
    pthread_detach(pthread_self());
    sleep(1);
    printf("Hello world\n");
    a = 8;
    b = 8;
    pthread_cond_signal(&cond);

}
int main(int argc,char * argv[])
{
    pthread_t tid;
    int result = pthread_create(&tid,NULL,delay_print,NULL);
    if(result != 0)
    {
        printf("create thread error\n");
        exit(0);
    }
    printf("printf form main\n");
    a = 6;
    b = 5;
    while(a != b)
    {
        pthread_cond_wait(&cond,&mutex);
    }
    printf("a= %d b = %d\n",a,b);
    pthread_exit(&result);
}
防止假唤醒

 

 一个条件变量只能对应一个互斥量。

一个互斥量可以对应多个条件变量。

mutex互斥锁必须是普通锁(PTHREAD_MUTEX_TIMED_NP)或者适应锁(PTHREAD_MUTEX_ADAPTIVE_NP),

且在调用pthread_cond_wait()前必须由本线程加锁(pthread_mutex_lock()),

而在更新条件等待队列以前,mutex保持锁定状态,并在线程挂起进入等待前解锁。

在条件满足从而离开pthread_cond_wait()之前,

mutex将被重新加锁,以与进入pthread_cond_wait()前的加锁动作对应。

posted @ 2014-04-17 11:16  李可以  阅读(370)  评论(1编辑  收藏  举报