首页 > 代码库 > 互斥量和条件变量的区别

互斥量和条件变量的区别

互斥量与条件变量的区别
转载自:http://www.360doc.com/content/12/0129/10/1317564_182456205.shtml
前面谈过了线程锁,下面我们在继续研究一下线程锁;
互斥量从本质上来说是一个锁,对互斥量加锁后任何其他试图给它加锁的线程都会被阻塞直至当前线程释放互斥量。
同样在设计时需要规定所有的线程必须遵守相同的数据访问规则,只有这样互斥机制才能正常工作(只要是锁都这样,这是锁工作的本质)
互斥量用pthread_mutex_t 数据类型表示,在使用互斥量之前我们必须对他进行初始话
pthread_mutex_init()函数可以帮你完成,同样释放前要调用pthread_mutex_destroy()函数。
对互斥量的操作:
int pthread_mutex_lock(); 对互斥量加锁,如若获取不到,则阻塞
int pthread_mutex_trylock();对互斥量加锁的非阻塞版本
int pthread_mutex_unlock();对互斥量解锁。
同样线程锁也存在死锁问题,这种低级问题不再讨论,下面重点说下条件变量:
开始条件变量把我也是搞的云里雾里,总感觉所谓的条件变量没有被用到,经过仔细的阅读终于感悟出其中真谛之一二
首先看一下数据类型及相关函数:
pthread_cond_t 数据结构用来定义条件变量的,同样他也有初始化和释放:
pthread_coud_init();
pthread_coud_destroy();
好了,条件变量要和互斥量一起使用,所以一般情况下会申明2个数据类型,在初始化他们2个,这个就不解释了
pthread_mutex_t count_lock;
pthread_cond_t count_ready;

pthread_mutex_init(&count_lock, NULL);
pthread_cond_init(&count_ready, NULL);
这四步是起手动作,就像70年代的防骑,起手3个buf,然后拿起盾向怪砸去。
起手动作做完了,就来分析一下条件变量的作用吧,其实这里的条件变量不是真正用来判断的条件,一般会定义一个变量
配合着while死循环来完成阻塞,而他本省则像一个桥梁,他通过这个桥梁等待另一个线程发送的信息,我们通过代码来分析一下,
void *A(void *arg)
   { 
        pthread_mutex_lock(&count_lock);//在调用pthread_coud_wait之前必须先锁住互斥量   
        /*等待满足条件,期间互斥量仍然可用*/
        while (count == 0)
                k = pthread_cond_wait(&count_ready, &count_lock);  //这个函数理解是关键,当这个函数调用的时候他会做2件事情,第一:他会把调用它的线程放到等待条件的线程列表上,(即通过条件变量传递消息的线程列表,可能多个线程同时等待)第二:对互斥量解锁(这个很关键哦,很多人不理解这个函数,就是因为不知到这个步骤),此时调用完后,线程就会阻塞在这里,知道通过条件变量传过来的解锁信号:pthread_coud_signal or pthread_coud_broadcast (2者的区别不多解释了)。
        printf("decrement :k = %d cout = %d%s\n", k, count , strerror(k));//打印返回值的类型,看是否成功
        count = count - 1;
        printf("decrement:count = %d\n",  count);
        pthread_mutex_unlock(&count_lock);
        pthread_exit(NULL);
}
从A线程来看,他已经基本死在那里了,除非有其他线程发送信号过来,下面B线程粉末登场:

void *B(void *arg)
{
        int k;
        pthread_mutex_lock(&count_lock);// 这句话看似平常 其实如果不理解A中所说,人然不知所意,从A线程上看我们知道他在阻塞时已经对互斥量解锁了,所以这里才能加锁
        不然的话,B也要在这里死翘翘了。
         sleep(3);睡眠3秒,这样容易分析结果

        count = count + 1; 这个才是解除A线程死循环的关键,当然不是解除阻塞,阻塞还是得我们的条件变量上场
        /*通知线程条件已满足,下面的2步顺序很关键,不然你可以打印A线程返回的K的错误类型,会报time out,原因就是没有先解锁在发送信号*/
        pthread_mutex_unlock(&count_lock);
        pthread_cond_signal(&count_ready);
        printf("increment:count = %d\n",  count);
        pthread_exit(NULL);
}

好了 在说一下pthread_cond_timedwait()
随便说一下了:从函数上看知道他有个时间,所以他不会一直等待,时间到了条件还没出现他就会重新获取互斥量然后返回错误类型,注意重新获取信号量 这句话
好了 ,我的理解全部都说出来了。