std::condition_variable::notify_one

void notify_one() noexcept;
(C++11 起)

若任何线程在 *this 上等待,则调用 notify_one 会解阻塞等待线程之一。

目录

参数

(无)

返回值

(无)

注意

notify_one()/notify_all() 的效果与 wait()/wait_for()/wait_until() 的三个原子部分的每一者(解锁+等待、唤醒和锁定)以能看做原子变量修改顺序单独全序发生:顺序对此单独的 condition_variable 是特定的。譬如,这使得 notify_one() 不可能被延迟并解锁正好在进行 notify_one() 调用后开始等待的线程。

通知线程不必保有等待线程所保有的同一互斥上的锁;实际上这么做是悲观的,因为被通知线程将立即再次阻塞,等待通知线程释放锁。然而一些实现(尤其是许多 pthread 的实现)辨识此情形,在通知调用中,直接从条件变量队列转移等待线程到互斥队列,而不唤醒它,以避免此“急促并等待”场景。

然而,在要求事件的精确调度时,锁下时期的通知可能是必须的,例如,若满足条件则线程将退出程序,导致析构通知线程的 condition_variable 的情况下。互斥解锁之后,但在通知前的虚假唤醒可能导致通知在被销毁对象上调用。

示例

#include <iostream>
#include <condition_variable>
#include <thread>
#include <chrono>
 
std::condition_variable cv;
std::mutex cv_m;
int i = 0;
bool done = false;
 
void waits()
{
    std::unique_lock<std::mutex> lk(cv_m);
    std::cout << "Waiting... \n";
    cv.wait(lk, []{return i == 1;});
    std::cout << "...finished waiting. i == 1\n";
    done = true;
}
 
void signals()
{
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::cout << "Notifying falsely...\n";
    cv.notify_one(); // 等待线程被通知 i == 0.
                     // cv.wait 唤醒,检查 i ,再回到等待
 
    std::unique_lock<std::mutex> lk(cv_m);
    i = 1;
    while (!done) 
    {
        std::cout << "Notifying true change...\n";
        lk.unlock();
        cv.notify_one(); // 等待线程被通知 i == 1 , cv.wait 返回
        std::this_thread::sleep_for(std::chrono::seconds(1));
        lk.lock();
    }
}
 
int main()
{
    std::thread t1(waits), t2(signals);
    t1.join(); 
    t2.join();
}

可能的输出:

Waiting... 
Notifying falsely...
Notifying true change...
...finished waiting. i == 1

参阅

通知所有等待的线程
(公开成员函数)
cnd_signalC 文档

版本历史

  • (当前 | 先前 2017年8月27日 (日) 20:09Fruderica讨论 | 贡献 . . (115字节) (-346). . (撤销)
  • 当前 | 先前 2013年7月2日 (二) 11:30P12bot讨论 | 贡献 . . (461字节) (-1). . (Use {{lc}}. Update links. Various fixes.) (撤销)
  • 当前 | 先前 2012年11月2日 (五) 20:25P12bot讨论 | 贡献 . . (462字节) (+385). . (r2.7.3) (机器人添加:de, en, es, fr, it, ja, pt, ru) (撤销)
  • 当前 | 先前 2012年10月26日 (五) 03:08P12讨论 | 贡献 . . (77字节) (0). . (1个修订: Translate from the English version) (撤销)
  • 当前 | 先前) 2012年10月22日 (一) 14:48TranslationBot讨论 | 贡献. . (77字节) (+77). . (Translated from the English version using Google Translate)