【问题标题】:If we use notify_one() to wake a thread, do we still need yield() - in C++?如果我们使用 notify_one() 来唤醒线程,我们还需要 yield() - 在 C++ 中吗?
【发布时间】:2019-03-04 03:24:27
【问题描述】:

yield():https://en.cppreference.com/w/cpp/thread/yield
notify_one():http://www.cplusplus.com/reference/condition_variable/condition_variable/notify_one/

案例:

线程 A 应该完成它正在做的任何事情,然后唤醒线程 B 来完成它的工作。

我在线程 A' run() 函数中编写了一个 notify_one() 调用。

是否可能出现线程 A 发出 notify_one() 信号但即使线程 B 已准备好仍会再次调度线程 A 的情况?

notify_one() 和 yield() 是等价的吗?

【问题讨论】:

  • 很明显,如果线程 A 正在等待 condvar 并且 condvar 没有发出信号,则线程 A 让出不会唤醒线程 B。
  • yieldnotify_one 之间没有任何共同之处。另外,“再次”是什么意思? A 继续运行。
  • 在 Linux 上 yield 可能对您的程序性能非常不利。它的实现假设您的线程没有其他事情可做,因此它被放置在调度优先级的最后。系统中的每个其他线程都将有机会在您产生的线程之前运行。

标签: c++ multithreading notifications yield


【解决方案1】:

yieldnotify_one 不相关。

yield 是一个进程请求(向操作系统)放弃其当前时间片。该线程仍将在下次安排。假设一个进程被分配了 10 毫秒。如果它在 5ms 后调用yield,则操作系统可以运行另一个进程。下次轮到它运行时,它仍然会得到完整的 10 毫秒。操作系统不必满足请求。

condition_variable::notify_onecondition_variable::wait 结合使用。如果有任何线程在等待,notify_one 保证会唤醒其中一个。如果没有线程在等待,notify_one 什么也不做。

请注意,条件变量在调用等待时必须与 1 个保护某些共享状态(条件)的互斥体一起使用,并且当条件为真时它正在等待另一个线程发出信号.

是否可能出现线程 A 发出 notify_one() 信号但即使线程 B 已准备好仍会再次调度线程 A 的情况?

是的。使用 Mesa 语义,向等待线程发出信号只会解除对另一个线程的阻塞。当前线程可能会继续运行,直到时间用完。使用 Hoare 语义,信号线程将立即切换到等待线程。然而,几乎所有条件的实现都使用 Mesa 语义。

notify_one() 和 yield() 是等价的吗?

“等效”意味着他们做同样的事情。事实并非如此。我想你的意思是问它们是否是互补的,或者它们是否属于同一个同步方案,答案是否定的,正如我上面解释的那样。

如果我们使用notify_one()唤醒一个线程,是否还需要yield()

如果线程 A 刚刚用nofity_one 唤醒线程 C,并且您希望尽快运行线程 C,您可以调用 yield 以放弃线程 A 的其余时间片。但是,操作系统不需要批准您的请求。并且可能在线程 C 之前安排了许多您无法控制的线程。

【讨论】:

    【解决方案2】:

    两者之间是有区别的。在您的情况下,您可能可以使用其中任何一个来获得相同的效果。 yield 更通用,notify_one 提供对程序流程的更多控制。

    yield:放弃处理器,以便操作系统可以调度任何其他线程。
    notify_one:发出条件信号,以便其中一个线程在此条件下等待 可以恢复。

    线程 A 应该完成它正在做的任何事情然后唤醒 线程 B 完成它的工作。

    notify_one 在这里是正确的选择,其中一个线程等待条件,而另一个线程可以发出信号。

    【讨论】:

    • yield 在什么意义上“更通用”?此外,“任何其他”是错误的,“任何(包括当前)”会好一点。
    • @Cubbi “可能安排任何其他线程”和“安排任何(包括当前)线程”不是等效的吗?除了前者增加了最有可能发生切换的压力。 (将当前线程推回队列中)notify_one 是特定同步机制的实现,而 yield 是更通用的 CPU 屈服。可能是我的英语不够好,在这里找不到更合适的词。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    相关资源
    最近更新 更多