使用多个互斥锁和条件变量

时间:2011-08-12 19:50:57

标签: c++ pthreads mutex race-condition producer-consumer

是否存在使条件变量使用多个互斥锁的机制? 我在Linux和pthreads用C ++。

在一个应用程序中,我需要两个互斥量(而不是一个)由pthread_cond_wait()以原子方式获取和释放,但该函数只接受一个。

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

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

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

问题在于,为了实现blockingManager,我还需要一个内部互斥锁,并且应该以原子方式获取和释放这两个互斥锁。

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

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

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

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

发信号通知condvar
  • 生产者线程分配新任务。

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

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

1 个答案:

答案 0 :(得分:5)

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

#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中找到它们。

相关问题