本文共 917 字,大约阅读时间需要 3 分钟。
我假设您正在使用
Dr Dobbs article中的无锁单生产者单一消费者队列 – 或类似的东西 – 所以我将使用那里的术语.
在这种情况下,您在“AFAICT”开头的段落中建议的答案是好的,但我认为它可以稍微优化:
>在消费者中 – 正如您所说,当消费者已经耗尽队列并且正在考虑休眠(并且只有那时)时,它会锁定互斥锁,再次检查队列,然后
>如果队列中有新项目,则释放互斥锁并继续工作
>或阻塞条件变量(当它唤醒时释放互斥锁以自然地找到非空队列).
>在制作人:
>首先拿一份最后一份,称之为saved_last
>像往常一样添加项目new_item,然后获取分隔符指针的副本,将其命名为saved_divider.
>如果saved_divider的值等于new_item,您刚插入的对象,则您的对象已被使用,您的工作已完成.
>否则,如果saved_divider的值不等于saved_last,则您不需要唤醒使用者.这是因为:
>在您添加新对象后严格来说,您知道分割器尚未到达new_item或saved_last
>自从你开始插入以来,last只有这两个值
>当分隔符等于最后一个时,消费者才会停止
>因此,消费者必须保持清醒,并在睡觉前到达您的新物品.
>否则锁定互斥锁,发出condvar信号然后释放互斥锁. (在此处获取互斥锁可确保您在消费者注意到队列为空并且实际上阻塞了condvar之间的时间内没有发出condar信号.)
这确保了在消费者趋于忙碌的情况下,当您知道消费者仍然醒着(并且不打算睡觉)时,您可以避免锁定互斥锁.它还最大限度地减少了互斥锁持有的时间,进一步降低了争用的可能性.
上面的解释非常冗长(因为我想要包含对其工作原理的解释,而不仅仅是算法的解释),但由此产生的代码应该非常简单.
当然,它实际上是否值得做,将取决于很多事情,我鼓励你衡量性能是否对你至关重要.在大多数情况下,mutex / condvar原语的良好实现在内部使用原子操作,因此它们通常只进行内核调用(最昂贵的位!)如果需要 – 即是否需要阻塞,或者肯定有一些线程在等待 – 所以不调用互斥函数节省的时间可能只相当于库调用的开销.
转载地址:https://blog.csdn.net/weixin_34262786/article/details/115412286 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!