多个线程访问的队列的推荐模式......工作线程应该做什么?

时间:2015-10-20 21:40:12

标签: c++ multithreading queue

我有一个由线程A添加的对象队列。线程B正在从队列中删除对象并处理它们。可能有许多线程A和许多线程B.

我正在使用互斥锁,当时正在推送队列,以及当"前面" ed" pop" ped,如图所示伪代码如下:

线程A调用此方法添加到队列中:

void Add(object)
{
    mutex->lock();
    queue.push(object);
    mutex->unlock();
}

线程B按如下方式处理队列:

object GetNextTargetToWorkOn()
{
    object = NULL;

    mutex->lock();
    if (! queue.empty())
    {
        object = queue.front();
        queue.pop();
    }
    mutex->unlock();

    return(object);
}

void DoTheWork(int param)
{
    while(true)
    {
        object structure;

        while( (object = GetNextTargetToWorkOn()) == NULL)
            boost::thread::sleep(100ms); // sleep a very short time

        // do something with the object
    }    
}

让我感到困扰的是那种 - 获取对象---睡眠 - 如果没有对象的范例。虽然有待处理的对象,但它很好。但是当线程正在等待工作时,存在两个问题

a)while循环正在消耗资源 b)睡眠意味着浪费时间是一个新的对象进来处理

是否有更好的模式来实现同样的目标?

2 个答案:

答案 0 :(得分:2)

你正在使用旋转等待,更好的设计是使用监视器。详细了解wikipedia的详细信息。 使用std :: condition_variable和一个很好的例子的跨平台解决方案可以找到here

答案 1 :(得分:0)

  

a)while循环正在消耗资源   b)睡眠意味着浪费时间是一个新的对象进来处理

根据我的经验,您使用的睡眠实际上“修复了”这两个问题。

a)资源的消耗是少量的ram,以及非常小的可用cpu周期。

b)睡眠是浪费在操作系统上的时间。

c)睡眠会影响“反应时间”(又称潜伏期),但很少出现问题(在中断之外)。

在睡眠中花费的时间可能比在这个简单循环中花费的时间长几个数量级。即它并不重要。

恕我直言 - 这是一个可以尽快放弃处理器的'好邻居'政策的实施。

在我的桌面上,AMD64双核,Ubuntu 15.04,信号量强制上下文切换需要大约13 us。

100 ms ==> 100,000 us ..这是4个数量级的差异,即非常微不足道。

在5个操作系统(Linux,vxWorks,OSE和其他几个嵌入式系统操作系统)中,我已经开始工作了,睡眠(或它们的等效)是放弃处理器的正确方法,因此它不会被阻止运行另一个一个线程处于睡眠状态时的线程。

注意:某些操作系统的睡眠可能无法放弃处理器。所以,你应该总是确认。我没找到一个。哦,但我承认我没有在Windows上查看/工作过。