1

考虑一个系统,其中一堆线程等待某些事务完成(请注意,多个线程可以等待单个事务)。为了使事务完成,其中一个线程必须运行一个分派循环。一旦当前运行调度循环的线程正在等待的事务完成,其他线程之一必须接管该工作。

在 Windows 上,这很容易实现:对于每个事务,事务完成时都会设置一个手动重置事件。此外,当调度循环退出时,会设置一个自动重置事件。每个线程同时等待两个事件。事务事件首先发出信号——在这种情况下线程退出——或者循环事件——在这种情况下线程运行调度循环。

我如何在 Linux(或者更好的 Posix)上实现这个?目前,我已经用bool变量替换了上面的事件,并且我有一个条件变量来表示其中一个发生了变化。但是,在这种安排中,线程会虚假地唤醒(每当一个事务完成时,所有线程都会唤醒)。有没有办法更好地实现这一点?

4

2 回答 2

4

我可能没有完全清楚您的情况,但我认为您可以在每个事务中使用一个条件变量(但仍然是一个互斥锁)。

当事务完成时,其相应的条件变量会发出信号;当调度循环退出时,所有条件变量都会发出信号。

于 2012-08-04T05:09:28.227 回答
0

我可能误解了你的要求。我会为一个事件创建一个抽象,并有一个事件队列。派生事件将被排队,并且线程正在等待队列非空的条件。入队会在条件变量上产生信号。

struct AnEvent {
    int type_;
    union {
        //...
    };
};

struct EventQ {
    std::mutex m_;
    std::condition_variable c_;
    std::list<AnEvent> q_;

    void enq (const AnEvent &e) {
        std::lock_guard<std::mutex> g(m_);
        bool was_empty = q_.empty();
        q_.push_back(e);
        if (was_empty) c_.notify_one();
    };

    void deq (AnEvent &e) {
        std::lock_guard<std::mutex> g(m_);
        while (q_.empty()) c_.wait(m_);
        e = q_.top();
        q_.pop_front();
        if (!q_.empty()) c_.notify_one();
    }
于 2012-08-04T03:28:46.913 回答