信号量(semaphore)与已经介绍过的 IPC 结构不同,它是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。
转载原文地址:https://www.jianshu.com/p/01ad36b91d39
一直以来都理解错了,不是使用条件变量再加上一对互斥锁,而是条件变量内部引入一个互斥锁,其实主要还是条件变量在起作用,这样会提高效率,看下面的例子。
while(true)
{
pthread_mutex_lock(&mutex);
iCount++;
pthread_mutex_unlock(&mutex);
}
//thread 2:
while(true)
{
pthread_mutex_lock(&mutex);
if(iCount >= 100)
{
iCount = 0;
}
pthread_mutex_unlock(&mutex);
}
这种实现下,就算 lock 空闲,thread2需要不断重复<加锁,判断,解锁>这个流程,会给系统带来不必要的开销。有没有一种办法让 thread2先被 block,等条件满足的时候再唤醒 thread2?这样 thread2 就不用不断进行重复的加解锁操作了?(现在只是互斥,想要实现一个同步)这就要用到条件变量了:
//thread1 :
while(true)
{
pthread_mutex_lock(&mutex);
iCount++;
pthread_mutex_unlock(&mutex);
pthread_mutex_lock(&mutex);
if(iCount >= 100)
{
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&mutex);
}
//thread2:
while(1)
{
pthread_mutex_lock(&mutex);
while(iCount < 100)
{
pthread_cond_wait(&cond, &mutex);
//这里的wait函数,在没有拿到信号之前,会一直处于阻塞等待的状态,不会像上一种情况不断的抢锁
//在这种情况下,wait住了就不会去抢锁,这样避免了线程之间的切换
}
printf("iCount >= 100\r\n");
iCount = 0;
pthread_mutex_unlock(&mutex);
}
需要注意的是,条件变量需要配合互斥锁来使用:
为什么要与pthread_mutex 一起使用呢? 这是为了应对 线程1在调用pthread_cond_wait()但线程1还没有进入wait cond的状态的时候,此时线程2调用了 cond_singal 的情况。 如果不用mutex锁的话,这个cond_singal就丢失了。如果等待时,条件不满足,那么就放锁,这样另一个线程就会拿到这个锁,继续运行,只有满足条件时,才会加锁。加了锁的情况是,线程2必须等到 mutex 被释放(也就是 pthread_cod_wait() 释放锁并进入wait_cond状态 ,此时线程2上锁) 的时候才能调用cond_singal.
简而言之就是,在thread 1 call pthread_cond_wait() 的时刻到 thread 1真正进入 wait 状态时,是存在着时间差的。如果在这段时间差内 thread2 调用了 pthread_cond_signal() 那这个 signal 信号就丢失了。给 wait 加锁可以防止同时有另一个线程在 signal。
使得效率变高是其一,
另外使用条件变量,避免了死锁的发生:
以上是关于效率问题,此外互斥锁还有一个缺点就是会造成死锁。
例如线程A和线程B都需要独占使用2个资源,但是他们都分别先占据了一个资源,然后又相互等待另外一个资源的释放,这样就形成了一个死锁。
条件变量起到了阻塞和唤醒线程的作用,所以通常互斥锁要和条件变量配合。
为了解决以上问题,条件变量常和互斥锁一起使用,条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。
---------------------
作者:似水流年0710
来源:CSDN
原文:https://blog.csdn.net/sishuiliunian0710/article/details/9625407
版权声明:本文为博主原创文章,转载请附上博文链接!