等待atomic_bool

coo*_*451 6 c++ multithreading atomic c++11

我有两个线程和一个由第二个线程设置的标志.我可以使用atomic_bool,但我希望能够等待*在第一个线程上设置标志.我怎样才能做到这一点?

我不能使用condition_variable我猜,因为如果第二个线程notify_one在第一个线程开始等待之前调用,则线程将不会唤醒.

此外,检查标志是否已经设置应该相当快.我想这应该很简单,但我只是卡住了,所以我在这里问.提前致谢.

*编辑:当然阻止,不忙 - 等待.对不起,如果不清楚.

coo*_*451 10

在cbreak和Ravadre(评论)的帮助下,我从这里得到了:

int main()
{
    std::mutex m;
    std::condition_variable cv;

    std::thread t([&] {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            std::unique_lock<std::mutex> lock(m);
            cv.wait(lock);
            std::cout << "Yay!\n";
    });

    cv.notify_one();
    t.join();
}
Run Code Online (Sandbox Code Playgroud)

这通常不会终止,到这里:

int main()
{
    std::mutex m;
    std::condition_variable cv;
    bool flag = false;

    std::thread t([&] {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::unique_lock<std::mutex> lock(m);
        cv.wait(lock, [&] { return flag; });
        std::cout << "Yay!\n";
    });

    {
        std::lock_guard<std::mutex> lock(m);
        flag = true;
    }

    cv.notify_one();
    t.join();
}
Run Code Online (Sandbox Code Playgroud)

这实际上是这项工作,但似乎仍然有很多不必要的开销.随意发布一个等效但更高性能(或更优雅)的答案,我很乐意接受它.请尽量使用standard-C++ 11,如果没有,请解释为什么standard-C++ 11不能这样做.

编辑:我还写了一个类safe_flag来封装它(再次感谢cbreak); 随意提出任何改进建议.

class safe_flag
{
    mutable std::mutex m_;
    mutable std::condition_variable cv_;
    bool flag_;

public:
    safe_flag()
        : flag_(false)
    {}

    bool is_set() const
    {
        std::lock_guard<std::mutex> lock(m_);
        return flag_;
    }

    void set()
    {
        {
            std::lock_guard<std::mutex> lock(m_);
            flag_ = true;
        }
        cv_.notify_all();
    }

    void reset()
    {
        {
            std::lock_guard<std::mutex> lock(m_);
            flag_ = false;
        }
        cv_.notify_all();
    }

    void wait() const
    {
        std::unique_lock<std::mutex> lock(m_);
        cv_.wait(lock, [this] { return flag_; });
    }

    template <typename Rep, typename Period>
    bool wait_for(const std::chrono::duration<Rep, Period>& rel_time) const
    {
        std::unique_lock<std::mutex> lock(m_);
        return cv_.wait_for(lock, rel_time, [this] { return flag_; });
    }

    template <typename Rep, typename Period>
    bool wait_until(const std::chrono::duration<Rep, Period>& rel_time) const
    {
        std::unique_lock<std::mutex> lock(m_);
        return cv_.wait_until(lock, rel_time, [this] { return flag_; });
    }
};
Run Code Online (Sandbox Code Playgroud)


Pet*_*ker 7

bool go = false;
std::mutex mtx;
std::condition_variable cnd;

// waiting thread:
std::unique_lock<std::mutex> lck(mtx);
while (!go)
    cnd.wait(lock);
// when we get here we know that go is true, and we have the lock

// signalling thread:
{
std::unique_lock<std::mutex> lck(mtx);
go = true;
cnd.notify_one();
}
// now we've released the lock, so the waiting thread will make progress
Run Code Online (Sandbox Code Playgroud)

  • @ cooky451-循环在这里是显式的,使初学者更清楚地了解正在发生的事情。 (2认同)
  • 不仅是显式的,而且`while(!go)`的语法比lambda表达式更简单(并且输入更少),而lambda表达式除了返回bool之外什么都不做 (2认同)