簡體   English   中英

std :: condition_variable :: with謂詞等待

[英]std::condition_variable::wait with predicate

在std :: condition_variable的文檔中,使用謂詞函數作為參數的wait()重載。 該函數將一直等到謂詞函數為true的第一次wake_up。

文檔中

據說這相當於:

while (!pred()) {
    wait(lock);
}

但是也:

在等待特定條件變為真時,可以使用此重載來忽略虛假喚醒。 請注意,在進入此方法之前,必須先獲取鎖,在wait(lock)退出后也必須重新獲取它,即鎖可以用作pred()訪問的保護。

我不確定要理解的是,這些嚴格地等效嗎(在這種情況下,我更喜歡普通的while循環,比我的情況下帶有lambda的重載更容易閱讀),或者重載(可能取決於實現)更有效?

為了避免測試條件為假時喚醒,實現是否可以在喚醒等待線程之前評估通知線程中的謂詞? 這里需要c ++線程大師...

謝謝

從性能的角度來看,實現可以嘗試使其比循環更好,但是我懷疑這樣做是否可行。 這是非常嚴格的,您可以檢查實現以查看完成情況。 這就是gcc 4.9.2在這里所做的:

template<typename _Predicate>
  void
  wait(unique_lock<mutex>& __lock, _Predicate __p)
  {
      while (!__p())
        wait(__lock);
  }

如您所見,它是完全一樣的,我懷疑是否可以在此做其他事情。 至於可讀性,它比循環更具可讀性。 但是,您可能會誤解其原因。 該循環僅用於檢查由條件保證的實變量確實確實更改為您期望的值-可能沒有。 常見的代碼片段如下所示:

cond_var.wait(lock, []() { return bool_var == true; })

據我了解,這兩個( while循環和wait + predicate )在功能上是等效的。 如果要使用while循環,則應在首次進入並評估循環條件之前獲取鎖定。 每隔兩次您還將持有該鎖,因為predicate()將在wait()完成后執行。

內部重載的作用相同:您必須在調用wait之前獲取鎖定,並且在wait完成之后,內部調用predicate()來檢查是否應繼續等待(就像while循環一樣)。

對於簡單謂詞,使用while循環返回boolean值更加清晰,也許您是對的。 但是如果predicate變得更復雜怎么辦? 為它定義一個專用函數並在while循環條件下使用它,還是在原處使用lambda? 如果謂詞數量增加,您將為每個謂詞定義功能嗎? 在我看來,在這種情況下使用lambda可以使代碼更清晰,因為整個事物都放在一個邏輯單元中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM