多线程虚假唤醒

在线程池中线程基于条件变量阻塞的时候有这样一个操作

        //无任务状态和不销毁时,线程阻塞等待
        while(pool->cur_queue_size == 0 && pool->shutdown != 1)
        {
            /* printf("线程[0x%lx]正在等待\n",pthread_self()); */
            pthread_cond_wait(&(pool->queue_cond),&(pool->queue_lock));//基于条件变量阻塞 
        }

思考这里为什么要有一个 while(pool->cur_queue_size == 0 && pool->shutdown != 1)这样的操作,没有这个不可以吗?
际上这里是在阻塞线程前判断了一下任务队列中有没有任务,如果有的话为什么还要阻塞线程然后在唤醒呢。直接不进入while循环而直接去执行任务。
那这里为什么不用if()呢?
这就引出一个虚假唤醒的问题,虚假唤醒就是说唤醒之后任务已经被执行了,该线程白白被唤醒而没有任务,甚至重复执行任务,引起错误操作。
想象这样一个场景

前情摘要
有一个队列,线程A的任务是先清空队列,然后检查队列是否为空,紧接着清空这个队列,B线程是获取队首元素,C线程讲一个元素入队。

首先,A线程将队列清空。

然后,B线程试图获得队首元素,但是队列目前是空,所以B解锁,基于条件变量阻塞,等待被唤醒。

然后,C线程将一个元素入队,条件变量成立,B线程被唤醒,准备加锁(场景定格),准备获取队首元素(未发生)。

但是,此时可能A线程可能同时要请求加锁(然后检测队列),所以此时A,B线程竞争这个锁。

假如,A得到了这个锁,并且清空了队列,然后释放了锁,此时B线程得到了锁(接上述被唤醒后请求加锁的状态),然后试图获得队首元素,但是此时队列已经为空,所以这是一个虚假唤醒。

解决办法就是用while(1)被唤醒后在检查一下这个任务是否还存在(pool->cur_queue_size == 0)。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值