Должен ли я синхронизировать вызовы mq_timedreceive при выполнении несколькими потоками? - PullRequest
4 голосов
/ 01 марта 2012

Я использую Posix Message Queues в Linux. По сути, у меня есть несколько потоков, которые получают сообщения из одной очереди по вызовам mq_timedreceive.

Если одновременно запущено несколько потоков и очередь не пуста, могу ли я гарантировать, что сообщение не будет получено более одного раза (т. Е. Сообщение не будет доставлено в несколько потоков)?

Конечно, я мог бы синхронизировать прием с мьютексом, но я хотел бы избежать этой блокировки, если это возможно. Я прочитал все справочные страницы (man mq_overview(3)), но не нашел ничего явного.

Заранее спасибо.

Ответы [ 2 ]

3 голосов
/ 05 марта 2012

Ядро делает эту блокировку за вас.

Посмотрите на реализацию в 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 имеет спин-блокировку, которая получается перед проверкой новых сообщений.

Последнее (pipelined_receive) - это то место, где сообщение удалено. Это защищено блокировкой info->, поэтому два потока не могут получить одно и то же сообщение.

2 голосов
/ 05 марта 2012

Эта справочная страница описывает это довольно хорошо:

http://pubs.opengroup.org/onlinepubs/009604499/functions/mq_receive.html

Если более чем один поток ожидает получения сообщения, когда сообщение поступает в пустую очередь иОпция «Приоритетное планирование» поддерживается, тогда для приема сообщения выбирается поток с наивысшим приоритетом, который ожидал дольше всего.В противном случае неизвестно, какой ожидающий поток получает сообщение.

Это позволяет вам использовать очереди сообщений POSIX для реализации потоков производителя / потребителя.

...