简体   繁体   English

condition_variable::notify_one 不会立即解除阻塞等待?

[英]condition_variable::notify_one does not instantly unblock wait?

I have a question about the notify_one function.我有一个关于 notify_one 函数的问题。 At the following code,在以下代码中,

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

std::condition_variable cv;
std::mutex m;
bool ready = false;

void f()
{
  std::unique_lock<std::mutex> lk(m);
  std::cout << "get into wait, ready=" << ready << std::endl;
  cv.wait(lk, []() { return ready; });
  std::cout << "get out of wait, ready=" << ready << std::endl;
}

int main()
{
  std::thread a(f);

  std::this_thread::sleep_for(std::chrono::seconds(1));

  {
    std::unique_lock<std::mutex> lk(m, std::defer_lock);
    if (lk.try_lock()) {
      std::cout << "main try_lock success, ready=" << ready << std::endl;
      ready = true;
    }
  }
  std::cout << "main notify, ready=" << ready << std::endl;
  cv.notify_one();

  // std::cout << "hello" << std::endl;

  {
    std::unique_lock<std::mutex> lk(m, std::defer_lock);
    if (lk.try_lock()) {
      std::cout << "main try_lock success, ready=" << ready << std::endl;
      ready = true;
    }
  }
  std::cout << "main notify, ready=" << ready << std::endl;
  cv.notify_one();

  a.join();

  return 0;
}

I get a following result,我得到以下结果,

get into wait, ready=0
main try_lock success, ready=0
main notify, ready=1
main try_lock success, ready=1
main notify, ready=1
get out of wait, ready=1

But I expect a below result, because, according to the page , if notify_one is called wait is unblocked and lock of mutex(m) is reacquired.但我希望得到以下结果,因为根据page ,如果调用 notify_one ,则等待解锁并重新获取 mutex(m) 的锁定。

get into wait, ready=0
main try_lock success, ready=0
main notify, ready=1
main notify, ready=1
get out of wait, ready=1

I found if I comment out the std::cout << "hello" << std::endl;我发现如果我注释掉std::cout << "hello" << std::endl; I get expected result.我得到了预期的结果。 Looks to me like notify_one does not immediately unblock the wait.在我看来,notify_one 不会立即解除等待。 It is correct?它是正确的?

Thank you very much!非常感谢!

Looks to me like notify_one does not immediately unblock the wait.在我看来,notify_one 不会立即解除等待。 It is correct?它是正确的?

Notification immediately unblocks the wait, meaning the wait is able to resume after the notification.通知立即解除等待,这意味着等待能够在通知后恢复。 That is, the sleeping thread is marked as runnable.也就是说,休眠线程被标记为可运行。

However, the scheduler doesn't necessarily re-start it immediately.但是,调度程序不一定会立即重新启动它。 If it would have to pre-empt some already running thread/process, it will probably wait until a yield, a syscall or some other cancellation point, and otherwise not even look at the newly-runnable thread until the end of the current timeslice.如果它必须抢占一些已经运行的线程/进程,它可能会等待直到产生、系统调用或其他一些取消点,否则在当前时间片结束之前甚至不会查看新运行的线程。

Unblocking something is not the same as forcing an immediate context switch (which is lucky, as otherwise synchronization would be even more expensive).解除阻塞与强制立即进行上下文切换不同(这是幸运的,否则同步会更加昂贵)。

After your first cv.notify_one();在你的第一个cv.notify_one(); you have no synchronization points (until a.join(); ) and the thread already running will most likely continue to run and reach a.join();您没有同步点(直到a.join(); )并且已经运行的线程很可能会继续运行并到达a.join(); before the scheduler decides to give the other thread a spin.在调度程序决定让另一个线程旋转之前。

As an experiment, you can yield the thread's execution slot by sleeping a little after notifying - and it may cause the order of the output to be what you expected.作为实验,您可以通过在通知后稍作休眠来让出线程的执行槽——这可能会导致输出的顺序与您预期的一样。

cv.notify_one();
std::this_thread::sleep_for(std::chrono::milliseconds(1));

Don't rely on it in production code though.但是不要在生产代码中依赖它。 This doesn't guarantee anything since there is no synchronization between the threads (other than the join() ).这不能保证任何事情,因为线程之间没有同步(除了join() )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 std::condition_variable wait() 和 notify_one() 同步 - std::condition_variable wait() and notify_one() synchronization 如果有很多线程在等待通知,std::condition_variable::notify_one() function 通知哪一个? - If there are many threads are waiting to be notify, which one does the std::condition_variable::notify_one() function notify? 在调用 std::condition_variable::wait() 之前多次调用 std::condition_variable::notify_one() - Calling std::condition_variable::notify_one() multiple times before std::condition_variable::wait() is called boost :: condition_variable :: notify_one()的行为 - Behavior of boost::condition_variable::notify_one() 是否有用于 std::condition_variable 的 notify_one() 队列? - Is there a `notify_one()` queue for `std::condition_variable`s? std :: condition_variable :: notify_one可重入吗? - Is std::condition_variable::notify_one reentrant? notify_one 不触发动态库中的condition_variable - notify_one not triggering condition_variable inside dynamic library boost :: condition_variable :: notify_one()上的并发 - concurrency on boost::condition_variable::notify_one() 为什么 std::condition_variable::notify_one 阻塞? - why is std::condition_variable::notify_one blocking? std::condition_variable::notify_one: 如果有些线程有错误的谓词,它会唤醒多个线程吗? - std::condition_variable::notify_one: does it wake multiple threads if some have false predicate?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM