什么是更好的消息队列?互斥& cond或互斥和信号量?

时间:2009-09-23 15:58:26

标签: c++ linux multithreading posix

我正在实现基于std :: queue。

的C ++消息队列

由于我需要popers在空队列中等待,我正在考虑使用互斥进行互斥,并且cond用于挂起空队列中的线程,因为glib会执行gasyncqueue。

然而,在我看来,互斥和信号量可以完成这项工作,我认为它包含一个整数,这似乎是一个非常高的数字,可以在待处理的消息上达到。

信号量的优点是你不需要每次从等待返回时手动检查条件,因为你现在确定有人插入了某些东西(当有人插入2个项目而你是第二个线程到达时)。

你会选择哪一个?

编辑: 更改了问题以回应@Greg Rogers

3 个答案:

答案 0 :(得分:4)

单个信号量不起作用 - 您需要比较(互斥+信号量)(互斥+条件变量)

通过尝试实现它很容易看到:

void push(T t)
{
    queue.push(t); 
    sem.post();
}

T pop()
{
    sem.wait();
    T t = queue.top();
    queue.pop();
    return t;
}

正如您所看到的,当您实际读取/写入队列时,即使信号(来自信号量)存在,也没有互斥。多个线程可以同时调用push并中断队列,或者多个线程可以同时调用pop并将其中断。或者,一个线程可以调用pop并删除队列的第一个元素,而另一个线程称为push。

你应该使用你认为更容易实现的,我怀疑性能会有很大差异(尽管测量可能很有趣)。

答案 1 :(得分:0)

我个人使用互斥来序列化对列表的访问,并通过套接字(由socketpair()生成)发送一个字节来唤醒使用者。这可能比信号量或条件变量的效率稍低,但它的优点是允许使用者阻塞select()/ poll()。这样,如果需要,消费者还可以等待除数据队列之外的其他事物。它还允许您在几乎所有操作系统上使用完全相同的排队代码,因为几乎每个操作系统都支持BSD套接字API。

Psuedocode如下:

// Called by the producer.  Adds a data item to the queue, and sends a byte
// on the socket to notify the consumer, if necessary
void PushToQueue(const DataItem & di)
{
   mutex.Lock();
   bool sendSignal = (queue.size() == 0);
   queue.push_back(di);
   mutex.Unlock();
   if (sendSignal) producerSocket.SendAByteNonBlocking();
}

// Called by consumer after consumerSocket selects as ready-for-read
// Returns true if (di) was written to, or false if there wasn't anything to read after all
// Consumer should call this in a loop until it returns false, and then
// go back to sleep inside select() to wait for further data from the producer
bool PopFromQueue(DataItem & di)
{
   consumerSocket.ReadAsManyBytesAsPossibleWithoutBlockingAndThrowThemAway();
   mutex.Lock();
   bool ret = (queue.size() > 0);
   if (ret) queue.pop_front(di);
   mutex.Unlock();
   return ret;
}

答案 2 :(得分:-1)

如果您希望一次允许多个用户同时使用您的队列,则应使用信号量。

sema(10) // ten threads/process have the concurrent access.

sema_lock(&sema_obj)
queue
sema_unlock(&sema_obj) 

Mutex一次只能“授权”一个用户。

pthread_mutex_lock(&mutex_obj)
global_data;
pthread_mutex_unlock(&mutex_obj) 

这是主要区别,您应该决定哪种解决方案符合您的要求。 但我选择互斥方法,因为您不需要指定有多少用户可以获取您的资源。