假设我们有一个单生产者线程、单消费者线程、无锁队列,并且生产者可能长时间不生产数据。在队列中没有任何数据时,让消费者线程休眠会很有益(节省电力并释放CPU以供其他进程/线程使用)。如果队列不是无锁的,则解决此问题的直接方法是让生产线程锁定互斥锁,执行其工作,发出条件变量信号并解锁,然后让读取线程锁定互斥锁,等待条件变量,进行读取,然后解锁。但是,如果我们使用无锁队列,使用互斥锁的方式将消除我们从一开始使用无锁队列获得的性能。
天真的解决方案是,在每次插入队列之后,使生产者锁定互斥锁,发出条件变量信号,然后解锁互斥锁,将实际工作(插入队列)完全保留在锁外,并使消费者执行相同的操作,锁定互斥锁,等待条件变量,解锁它,将所有东西从队列中取出,然后重复,将队列的读取保持在锁外。这里存在竞态条件:在读者从队列中取出并进入睡眠状态之间,生产者可能已经向队列中插入了一个项目。现在,读者将进入睡眠状态,并可能一直保持这种状态,直到生产者再次插入另一个项目并再次发出条件变量信号。这意味着您偶尔可能会发现特定项目需要很长时间才能通过队列传输。如果您的队列始终处于活动状态,则可能不会有问题,但是如果它始终处于活动状态,则可以完全忘记条件变量。
据我所知,解决方案是使生产者的行为与使用常规需锁定队列时相同。它应该锁定互斥锁,插入无锁队列,发出条件变量信号,然后解锁。但是,消费者应该有所不同。当它醒来时,它应立即解锁互斥锁,而不是等待读取队列。然后,它应尽可能多地拉取队列并处理它。最后,只有当消费者想要进入睡眠状态时,它才应锁定互斥锁,检查是否有任何数据,然后如果有,则解锁并处理它,否则等待条件变量。这样,互斥锁的争用次数比锁满队列少,但没有风险在队列上留下数据就进入睡眠状态。
这是最好的方法吗?还有其他选择吗?
注意:'最快'实际上是指'最快而不需专用核心反复检查队列',但这无法适合标题;p 一个替代方案:采用天真的解决方案,但让消费者等待条件变量,等待时间与您愿意容忍项目通过队列所需的最大延迟相对应。但是,如果所需的超时时间相当短,则可能低于您的操作系统的最小等待时间或仍会消耗太多的CPU。
天真的解决方案是,在每次插入队列之后,使生产者锁定互斥锁,发出条件变量信号,然后解锁互斥锁,将实际工作(插入队列)完全保留在锁外,并使消费者执行相同的操作,锁定互斥锁,等待条件变量,解锁它,将所有东西从队列中取出,然后重复,将队列的读取保持在锁外。这里存在竞态条件:在读者从队列中取出并进入睡眠状态之间,生产者可能已经向队列中插入了一个项目。现在,读者将进入睡眠状态,并可能一直保持这种状态,直到生产者再次插入另一个项目并再次发出条件变量信号。这意味着您偶尔可能会发现特定项目需要很长时间才能通过队列传输。如果您的队列始终处于活动状态,则可能不会有问题,但是如果它始终处于活动状态,则可以完全忘记条件变量。
据我所知,解决方案是使生产者的行为与使用常规需锁定队列时相同。它应该锁定互斥锁,插入无锁队列,发出条件变量信号,然后解锁。但是,消费者应该有所不同。当它醒来时,它应立即解锁互斥锁,而不是等待读取队列。然后,它应尽可能多地拉取队列并处理它。最后,只有当消费者想要进入睡眠状态时,它才应锁定互斥锁,检查是否有任何数据,然后如果有,则解锁并处理它,否则等待条件变量。这样,互斥锁的争用次数比锁满队列少,但没有风险在队列上留下数据就进入睡眠状态。
这是最好的方法吗?还有其他选择吗?
注意:'最快'实际上是指'最快而不需专用核心反复检查队列',但这无法适合标题;p 一个替代方案:采用天真的解决方案,但让消费者等待条件变量,等待时间与您愿意容忍项目通过队列所需的最大延迟相对应。但是,如果所需的超时时间相当短,则可能低于您的操作系统的最小等待时间或仍会消耗太多的CPU。