0

我有一个线程让我们称之为 t1,它会在 x 秒后定期发送一些东西。这个“x 秒部分”可以从其他线程 (t2)更改。我应该能够从线程 t1 执行以下操作。

  1. 等待“x 秒”然后发送一些东西
  2. 如果线程 t2 发送另一个 "x" 值,则不要发送,而是转到第 1 步。

我为此目的使用了条件变量 wait_for()

我只想在“x 秒”结束时发送。

目前我已经在没有谓词的情况下实现了它(因为我不需要它)是这样的:

auto done = wait_for(lock,x seconds);

if(done == cv_status::timeout) 
{
/*perform send operation*/
}

但有时我会在 timeout 之前看到“发送发生”,我认为这是由于虚假唤醒和缺少谓词造成的。

我的问题是如何在没有谓词的情况下处理虚假唤醒?我应该为此采取另一种方法吗?我不需要谓词,因为线程 t1 在特定条件下休眠(当 x 为 0 时)并且我希望它(t1)在没有任何条件的情况下被 t2 唤醒。

这是我第一个使用 cond 变量的任务,我还在学习 CPP,提前谢谢你。

4

2 回答 2

1

不,没有谓词就无法避免虚假唤醒。首先,这就是谓词的用途。C++ 标准明确允许等待偶尔出现虚假唤醒,并且没有办法阻止它们。

您唯一的选择是:

  1. 使用谓词

  2. 不要使用谓词,但要考虑到您可能会对整体逻辑进行虚假唤醒。您无法防止虚假唤醒,因此请调整程序的逻辑以适应它们。

例如:在这种情况下,您的目标是等待一段时间。所以,在等待之前,看看std::chrono::steady_clock::now()说了什么,并计算在给定的时间段过去后它应该说什么。然后在您据称等待规定的时间后再次检查。如果仍然小于预期的超时时间,请计算剩余的时间,然后再次等待,希望下次运气更好。起泡,冲洗,重复。

在所有情况下,请记住,即使没有虚假唤醒,您也几乎无法保证。即使您要求在整整五秒钟后唤醒,也可能需要一点时间才能wait_for()返回。相应地规划你的整体逻辑。

于 2021-10-10T12:20:56.330 回答
0

您确实需要一个谓词,因为您需要区分虚假唤醒和合法唤醒。

您可以做的是添加一个std::atomic<bool>告诉您 t2 是否发送了 x 更新的 a。当 t2 发送更新时,它也会设置这个原子布尔值。t2 在唤醒时使用它来忽略虚假唤醒,然后将其清除。

于 2021-10-10T12:17:00.103 回答