一段代码引发的思考
最近一直都在看Linux_c,在条件变量一节的学习中遇到一些疑惑,先看代码吧
#include <stdio.h>
#include<unistd.h>
#include <pthread.h>
pthread_mutex_t mutex;
pthread_cond_t cond;
void *thread1(void *arg)
{
pthread_cleanup_push(pthread_mutex_unlock, &mutex); //提供函数回调保护
while (1){
printf("thread1 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("thread1 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(4);
}
pthread_cleanup_pop(0);
}
void *thread2(void *arg)
{
while (1) {
printf("thread2 is running\n");
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);
printf("thread2 applied the condition\n");
pthread_mutex_unlock(&mutex);
sleep(1);
}
}
int main()
{
pthread_t thid1, thid2;
printf("condition variable study!\n");
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_create(&thid1, NULL, (void *) thread1, NULL);
sleep(3);
pthread_create(&thid2, NULL, (void *) thread2, NULL);
do{
pthread_cond_signal(&cond);
} while (1);
sleep(20);
pthread_exit(0);
return 0;
可以看到thread1和thread2中均由互斥锁和条件变量的配合。
书上对互斥锁的解释为
使用条件变量主要包括两个动作:一个等待使用资源的线程等待“条件变量被设置为真”;另一个线程在使用完资源后“设置条件为真”,这样就可以保证线程的同步。
而条件变量主要包括两个动作
一个等待使用资源的线程等待“条件变量被设置为真”;另一个线程在使用完资源后“设置条件为真“
进一步思考
博主一直觉得互斥锁和条件变量配合很多余,两者都可以阻塞线程,使用互斥锁可以保证条件变量能被正确的修改,这个可以理解,那为什么不直接使用互斥锁,反倒更加方便。后来看到pthread_cond_wait的参数更不可思议
#include <pthread.h>
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
cond可以理解,为什么还要mutex。此二者必有重大关系
后来就查查查 ……
真相揭晓
互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起配合使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线程间的同步。
两个线程操作同一临界区时,通过互斥锁保护,若A线程已经加锁,B线程再加锁时候会被阻塞,直到A释放锁,B再获得锁运行,进程B必须不停的主动获得锁、检查条件、释放锁、再获得锁、再检查、再释放,一直到满足运行的条件的时候才可以(而此过程中其他线程一直在等待该线程的结束),这种方式是比较消耗系统的资源的。而条件变量同样是阻塞,还需要通知才能唤醒,线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,该线程就休眠了,应该仍阻塞在这里,等待条件满足后被唤醒,节省了线程不断运行浪费的资源。这个过程一般用while语句实现。当线程B发现被锁定的变量不满足条件时会自动的释放锁并把自身置于等待状态,让出CPU的控制权给其它线程。其它线程 此时就有机会去进行操作,当修改完成后再通知那些由于条件不满足而陷入等待状态的线程。这是一种通知模型的同步方式,大大的节省了CPU的计算资源,减少了线程之间的竞争,而且提高了线程之间的系统工作的效率。这种同步方式就是条件变量。
这就类似于我们上课时候睡觉,不加条件变量就是一边睡觉还一边得小心老师,这样睡觉是十分没有质量的;而条件变量就类似与我们的同桌,当老师来时候同桌会叫醒你,这样就可以舒舒服服的睡觉了 。
浅谈互斥锁为什么还要和条件变量配合使用