对于消息队列,什么更好?互斥;cond或mutex&;信号灯? 我正在基于STD::Que./P>实现C++消息队列

对于消息队列,什么更好?互斥;cond或mutex&;信号灯? 我正在基于STD::Que./P>实现C++消息队列,c++,linux,multithreading,posix,C++,Linux,Multithreading,Posix,由于我需要popers在空队列上等待,所以我考虑使用互斥来实现互斥,使用cond来暂停空队列上的线程,就像glib在gasyncqueue上所做的一样 然而,在我看来,互斥量和信号量可以完成这项工作,我认为它包含一个整数,对于挂起的消息来说,这似乎是一个相当高的数字 信号量的优点是,您不需要在每次等待返回时手动检查条件,因为您现在可以确保有人插入了某些内容(当有人插入了2个项目,而您是第二个到达的线程时) 你会选择哪一个 编辑: 将问题更改为@Greg Rogers如果您希望同时允许多个用户使用

由于我需要popers在空队列上等待,所以我考虑使用互斥来实现互斥,使用cond来暂停空队列上的线程,就像glib在gasyncqueue上所做的一样

然而,在我看来,互斥量和信号量可以完成这项工作,我认为它包含一个整数,对于挂起的消息来说,这似乎是一个相当高的数字

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

你会选择哪一个

编辑:
将问题更改为@Greg Rogers

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

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

sema_lock(&sema_obj)
queue
sema_unlock(&sema_obj) 
互斥锁一次只“授权”一个用户

pthread_mutex_lock(&mutex_obj)
global_data;
pthread_mutex_unlock(&mutex_obj) 
这是主要的区别,您应该决定哪个解决方案适合您的需求。
但我会选择互斥方法,因为您不需要指定有多少用户可以获取您的资源

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

密码如下:

// 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;
}

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

通过尝试实现它,很容易看出这一点:

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


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

这不是重点,不是比较互斥和信号量,我是比较互斥和信号量,用于信号传递和互斥,而不仅仅是互斥。嗯,你是对的,我没有正确地询问它,我使用互斥来访问数据,除了信号量。