对一个条件变量使用多个互斥锁 [英] Using more than one mutex with a conditional variable

查看:140
本文介绍了对一个条件变量使用多个互斥锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种机制可以让条件变量使用多个互斥锁?我在 Linux 中,在 C++ 中使用 pthreads.

Is there a mechanism to have a conditional variable use multiple mutexes? I am in Linux and pthreads in C++.

在一个应用程序中,我需要通过 pthread_cond_wait() 原子地获取和释放两个互斥体(而不是一个),但该函数只接受一个.

In an application, I need two mutexes (instead of one) to be atomically acquired and released by pthread_cond_wait(), but the function only accepts one.

我有一个名为 BlockingManager 的类,它有方法:

I have a class named BlockingManager and it has the method:

blockMeFor( pthread_cond_t* my_cond, pthread_mutex_t* my_lock, set<int> waitees);

我正在使用它,假设它像 pthread_cond_wait 一样获取/释放互斥锁.

and I am using it, assuming that it acquires/releases the mutex just like pthread_cond_wait.

问题是为了实现blockingManager,我也需要一个内部互斥锁,并且这两个互斥锁都应该被原子地获取和释放.

The problem is that for implementing blockingManager I need an internal mutex too and both of these mutexes should be acquired and released atomically.

这里有一个相关的讨论,它说等待多个互斥量会产生未定义的行为.http://sourceware.org/ml/libc-help/2011-04/msg00011.html

There is a somehow related discussion here, it says waiting for more than one mutex yields undefined behavior. http://sourceware.org/ml/libc-help/2011-04/msg00011.html

我面临的问题的生产者/消费者模型如下:

A producer/consumer model for the problem I am facing follows:

我们有多个客户.每个客户都有一些任务.每个任务可能有多个先决条件(在同一客户端或其他客户端的任务之间).每个客户端都有一个消费者线程.任务从一个生产者线程分配给客户端.新分配的任务可能有资格在先前的任务之前完成.有些时候可能没有任务要做,但如果有任务要做,至少应该做一个.(应该是节约工作的)

We have multiple clients. Each client has some tasks. Each task probably has multiple prerequisites (either among the tasks of the same client or other clients). Each client has one consumer thread. The tasks are assigned to the clients from one producer thread. The newly assigned task may be eligible to be done before the previous tasks. There may be no task to be done at some moments, but if there is a task to be done, at least one should be done. (It should be work-conserving)

我为每个消费者线程使用一个 condvar,一旦该线程没有任务要完成,它就会阻塞.条件变量可以通过

I am using one condvar per consumer thread and it would block once there is no task to be done for that thread. The condvar may be signaled by either

  • 分配新任务的生产者线程.

  • The producer thread assigning a new task.

另一个完成任务的消费者线程.

Another consumer thread finishing a task.

我为每个消费者使用一个互斥锁来保护生产者和生产者之间的共享数据结构.消费者.还有一个互斥锁(内部互斥锁)来保护多个消费者之间的共享数据结构.

I am using one mutex per consumer to protect the shared data-structures between producer & consumer. And one mutex (internal mutex) to protect the shared data-structures between multiple-consumers.

推荐答案

在 C++11(如果您的编译器支持)中,您可以使用 std::lock 一次锁定两个互斥锁(没有死锁).您可以使用它来构建一个引用两个互斥锁的 Lock2 类.然后你可以使用 std::condition_variable_any 来等待 Lock2.这一切可能看起来像:

In C++11 (if your compiler supports it) you can use std::lock to lock two mutexes at once (without deadlock). You can use this to build a Lock2 class which references two mutexes. And then you can use std::condition_variable_any to wait on a Lock2. This all might look something like:

#include <mutex>
#include <condition_variable>

std::mutex m1;
std::mutex m2;
std::condition_variable_any cv;

class Lock2
{
    std::mutex& m1_;
    std::mutex& m2_;

public:
    Lock2(std::mutex& m1, std::mutex& m2)
        : m1_(m1), m2_(m2)
    {
        lock();
    }

    ~Lock2() {unlock();}

    Lock2(const Lock2&) = delete;
    Lock2& operator=(const Lock2&) = delete;

    void lock() {std::lock(m1_, m2_);}
    void unlock() {m1_.unlock(); m2_.unlock();}
};

bool not_ready() {return false;}

void test()
{
    Lock2 lk(m1, m2);
    // m1 and m2 locked
    while (not_ready())
        cv.wait(lk);  // m1 and m2 unlocked
    // m1 and m2 locked
}  // m1 and m2 unlocked

如果您的编译器尚不支持这些工具,您可以在 boost 中找到它们.

If your compiler does not yet support these tools, you can find them in boost.

这篇关于对一个条件变量使用多个互斥锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆