C++面试问题:为什么条件变量要和互斥锁一起使用?

C++面试常见问题:为什么条件变量要和互斥锁一起使用?

首先解释,为什么要引入条件变量?

假设存在这样一种情况,多个类似的线程需要等待某一条件达成,才能继续任务,条件属于临界资源,在访问时需要加锁。假设不存在条件变量,那么解决方案可能是如下这样:

while(true)
{
	lock();
	if(条件满足)
	{
		doSomething();
	}
	unlock();
}

如上所示,在条件未满足之前,会不断的加锁再解锁,这种不断的查询操作是浪费资源的(预留:为什么浪费资源?)。

引入条件变量后,若条件不满足,则相应线程被阻塞直至条件发生变化被唤醒,再去查询条件是否满足,避免了上述条件变化发生之前的无用查询包括加解锁。

条件变量的引入,使多个线程以一种无竞争的方式等待条件的改变

第二,为什么条件变量要和互斥锁一起使用?

其一,在pthread_cond_wait()前,需要进行条件判断,而此条件属于临界资源,需要在访问前加锁,此为保护临界资源的需要。
其二,这也是面试官关注的,可以把问题转化为:为什么pthread_cond_wait()需要传入一锁作为参数?

当条件不满足时,pthread_cond_wait()内部将执行两个步骤,并保证两个操作的原子性:
1.将当前线程加入条件信号的等待队列。
2.解作为参数传入的锁,解除对临界资源的锁定。

用反证法证明,若去掉锁参数pthread_cond_wait()将只执行步骤1,则可能的代码如下:

lock();
while(条件不满足)
{
	unlock();//#1:解除对临界资源的锁定。
	pthread_cond_wait(condA);//#2:当前线程加入等待队列,阻塞
	lock();//#3:再次判断之前,对临界资源保护
}
doSomething();
unlock();

要注意到,#1和#2两步已经不是原子操作了,那么就有可能有如此情景:
在当前线程(A)执行完#1行代码后到执行#2代码前的时间间隔里,另一线程(B),获取到了锁,修改了条件使其满足,然后发送了信号condA。而此时线程A还未被加入到condA的等待队列中,造成线程A错过了通知一直阻塞,直至下一次通知,如果没有下一次通知,那么A将永远等待下去,比如B也需要A的相关条件变量通知才能再次发出condA的通知。此时逻辑已经出了问题,而如果保证#1和#2的原子性可以避免出现上述问题。

此为,为保证“解锁”和“加入等待队列”两操作的原子性,从而避免可能发生的死锁需要。

参与评论 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

August8757

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值