std :: condition_variable :: notify_all()-我需要一个例子

Aka*_*ata 1 c++ multithreading condition-variable

我需要一个使用notify_all()方法的示例。因为我不知道它应该如何工作。

每个等待线程均以如下代码开头:

std::unique_lock<std::mutex> lock(mutex);
condition_variable.wait(lock, [](){return SOMETHING;});
Run Code Online (Sandbox Code Playgroud)

从一开始,等待线程就需要获取互斥体。因此,如果有多个等待线程,则其余线程将等待锁定互斥锁。那么,如果等待线程卡在锁定互斥锁上并且根本不执行方法wait(),那么使用notify_all()的目的是什么?这些线程将一个接一个地唤醒,而不是同时唤醒。

Ric*_*ges 5

互斥锁保护的内部状态condition_variable。调用waitcondition_variable引起互斥被解锁。因此,在等待时,线程不拥有互斥体。

wait完成时,再次互斥是调用之前(原子)获得的wait回报。

线程没有在互斥体上竞争,它们是在条件本身上竞争。

如果您愿意,可以在等待返回后立即解锁。例如,如果要允许多个线程在一个条件上进行同步,这就是您的方式。您也可以使用此功能来实现信号量。

例:

此代码处理的事情在10注意分批notify_all()unlock()

#include <condition_variable>
#include <mutex>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>
#include <vector>

void emit(std::string const& s)
{
    static std::mutex m;
    auto lock = std::unique_lock<std::mutex>(m);
    std::cout << s << std::endl;
}

std::mutex m;
std::condition_variable cv;
int running_count = 0;

void do_something(int i)
{
    using namespace std::literals;

    auto lock = std::unique_lock<std::mutex>(m);
    // mutex is now locked

    cv.wait(lock,   // until the cv is notified, the mutex is unlocked 
            [] 
            {
                // mutex has been locked here 
                return running_count < 10; 
                // if this returns false, mutex will be unlocked again, but code waits inside wait() for a notify()
            });
    // mutex is locked here
    ++running_count;
    lock.unlock();
    // we are doing work after unlocking the mutex so others can also
    // work when notified
    emit("running " + std::to_string(i));
    std::this_thread::sleep_for(500ms);
    // manipulating the condition, we must lock
    lock.lock();
    --running_count;
    lock.unlock();
    // notify once we have unlocked - this is important to avoid a pessimisation.
    cv.notify_all();
}

int main()
{
    std::vector<std::thread> ts;
    for (int i  = 0 ; i < 200 ; ++i)
    {
        ts.emplace_back([i] { do_something(i); });
    }

    for (auto& t : ts) {
        if (t.joinable()) t.join();
    }

}
Run Code Online (Sandbox Code Playgroud)

  • @RichardHodges,在任何给定时间只有一个线程可以持有“锁”,并且在该线程持有锁之前“cv.wait()”不可能返回。所以,是的,它同时_唤醒_它们,但“唤醒”仅意味着线程从条件变量的队列移动到互斥队列。它们不会同时获得锁并从 wait() 返回。 (3认同)