簡體   English   中英

有沒有一種安全的方法可以在std :: future上調用wait()?

[英]Is there a safe way to call wait() on std::future?

C ++ 11標准說:

30.6.6類模板未來

(3)“調用除析構函數,移動賦值運算符以外的任何成員函數的效果,或對未定義的valid() == false的未來對象的valid() == false 。”

那么,這是否意味着以下代碼可能會遇到未定義的行為?

void wait_for_future(std::future<void> & f)
{
    if (f.valid()) {
        // what if another thread meanwhile calls get() on f (which invalidates f)?
        f.wait();
    }
    else {
        return;
    }
}

Q1:這真的是一種可能的未定義行為嗎?

Q2:是否有任何符合標准的方法來避免可能的未定義行為?

請注意,該標准有一個有趣的注釋[也在30.6.6(3)]:

“[注意:鼓勵實現檢測此情況並拋出future_error類型的對象,其錯誤條件為future_errc::no_state endnote]”

Q3:如果我只依賴標准的音符並且只使用f.wait()而不檢查f的有效性,這樣可以嗎?

void wait_for_future(std::future<void> & f)
{
    try {
        f.wait();
    }
    catch (std::future_error const & err) {
        return;
    }
}

編輯:收到答案和進一步研究該主題后的摘要

事實證明,我的例子的真正問題不是直接由於並行修改(從單個線程調用單個修改get ,另一個調用valid wait並且wait哪個是安全的)。

真正的問題是std::future對象的get函數是從不同的線程訪問的,這不是預期的用例! std::future對象只能在單個線程中使用!

涉及的唯一其他線程是設置共享狀態的線程:通過從傳遞給std::async的函數返回或者在相關的std::promise對象上調用set_value等。

更多:甚至wait來自另一個線程的std::future對象不是預期的行為(由於與我的示例#1中的UB非常相同)。 我們將在這個用例中使用std::shared_future ,讓每個線程都擁有一個std::shared_future對象的副本。 請注意,所有這些都不是通過同一個共享std::future對象,而是通過單獨的(相關)的對象!

底線:這些對象不應在線程之間共享。 在每個線程中使用單獨的(相關的)對象。

正常的std::future本身並不是線程安全的。 所以是的,它是UB,如果你調用從單個std::future上的多個線程修改函數,因為你有潛在的競爭條件。 雖然,從多個線程調用wait是可以的,因為它是const / non-modification。

但是,如果你真的需要從多個線程訪問std::future的返回值,你可以先調用std::future::share來獲得一個std::shared_future ,你可以將它復制到每個線程然后每個線程都可以調用get 請注意,每個線程都有自己的std::shared_future對象非常重要。

你只需要檢查有效,如果你的未來可能是無效的,那么正常的用例( std::async等)和正確的用法(例如:不是callig get兩次)不是這種情況。

期貨允許您從一個線程存儲狀態並從另一個線程檢索它。 它們不提供任何進一步的線程安全性。

這真的是一種可能的未定義行為嗎?

如果你有兩個線程試圖在沒有同步的情況下獲得未來的狀態,是的。 我不知道為什么你會這樣做。

是否有任何符合標准的方法來避免可能的未定義行為?

只嘗試從一個線程獲取狀態; 或者,如果您確實需要在線程之間共享它,請使用互斥鎖或其他同步。

如果我只依靠標准的說明,那沒關系

如果您知道您需要支持的唯一實現遵循該建議,是的。 但是沒有必要。

並且只使用f.wait()而不檢查f的有效性?

如果你沒有做任何多線程訪問未來的怪異惡作劇,那么你可以假設它是有效的,直到你檢索到狀態(或將其移動到另一個未來)。

暫無
暫無

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

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