我在Linux上使用Posix Message Queues。基本上,我有多个线程通过调用mq_timedreceive
来接收来自同一队列的消息。我是否应该在由多个线程执行时同步mq_timedreceive调用?
如果同时运行多个线程且队列不是空的,我保证消息不会被多次接收(即消息不会传递给多个线程)吗?可以肯定的是,我可以将接收与一个互斥锁同步,但是如果可能的话,我想避免这个锁。我阅读了所有手册页(man mq_overview(3)
),但没有发现任何明确的内容。
在此先感谢。
我在Linux上使用Posix Message Queues。基本上,我有多个线程通过调用mq_timedreceive
来接收来自同一队列的消息。我是否应该在由多个线程执行时同步mq_timedreceive调用?
如果同时运行多个线程且队列不是空的,我保证消息不会被多次接收(即消息不会传递给多个线程)吗?可以肯定的是,我可以将接收与一个互斥锁同步,但是如果可能的话,我想避免这个锁。我阅读了所有手册页(man mq_overview(3)
),但没有发现任何明确的内容。
在此先感谢。
内核为你锁定。
看在IPC/mqueue.c实现:
SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
size_t, msg_len, unsigned int __user *, u_msg_prio,
const struct timespec __user *, u_abs_timeout)
{
...
struct mqueue_inode_info *info;
...
filp = fget(mqdes);
if (unlikely(!filp)) {
ret = -EBADF;
goto out;
}
inode = filp->f_path.dentry->d_inode;
...
spin_lock(&info->lock);
if (info->attr.mq_curmsgs == 0) {
if (filp->f_flags & O_NONBLOCK) {
spin_unlock(&info->lock);
...
} else {
msg_ptr = msg_get(info);
inode->i_atime = inode->i_mtime = inode->i_ctime =
CURRENT_TIME;
/* There is now free space in queue. */
pipelined_receive(info);
spin_unlock(&info->lock);
ret = 0;
}
每个mqueue中有一个自旋锁,这是检查新邮件之前获得的。
last else(pipelined_receive)是消息出列的地方。这受到info-> lock的保护,所以两个线程无法获得相同的消息。
本手册页介绍了它相当不错:
http://pubs.opengroup.org/onlinepubs/009604499/functions/mq_receive.html
如果有多个线程在等待时,一个消息到达一个空队列和优先级调度选项支持接收消息,那么应选择等待时间最长的最高优先级线程来接收消息。否则,未指定哪个等待线程收到该消息。
这允许您使用POSIX消息队列来实现生产者/消费者线程。
我浏览了'ipc/mqueue.c'文件,但是我不确定锁'lock'是否确实阻止将消息发送到多个接收者。你能详细说明你的答案吗? – 2012-03-05 11:32:54