簡體   English   中英

std :: call_once是阻塞調用嗎?

[英]Is std::call_once a blocking call?

我在我的代碼中使用std::call_once只初始化一些共享變量一次。 調用代碼位於由多個線程觸發的回調內。 我有興趣知道,因為我在文檔中找不到它是std::call_once是否阻塞,就好像有一個std::lock_guard 在實踐中,看起來就是這種情況。

例如,以下將在調用任何print()之前打印"Done"

#include <future>
#include <iostream>
#include <thread>
#include <mutex>

std::once_flag flag;

void print()
{
    for(int i=0;i<10;i++)
    {
          std::cout << "Hi, my name is " << std::this_thread::get_id() 
            << ", what?" << std::endl;
    }
}

void do_once()
{
    std::cout << "sleeping for a while..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << "Done" << std::endl;
}

void work()
{
    std::call_once(flag, [](){ do_once(); });
    print();
}


int main()
{
    auto handle1 = std::async(std::launch::async, work);
    auto handle2 = std::async(std::launch::async, work);
    auto handle3 = std::async(std::launch::async, work);
    auto handle4 = std::async(std::launch::async, work);

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}

我假設情況確實如此(因為我看不出它是如何實現的),但這種行為是否得到保證,或者是否有編譯器決定std::call_once確實會被調用一次但是允許其他線程繼續,只是忽略這個調用?

是的std::call_once是一個阻塞調用。 來自[thread.once.callonce]我們有

效果:不調用其func的call_once的執行是被動執行。 調用其func的call_once的執行是一個活動執行。 活動執行應調用INVOKE (DECAY_COPY ( std::forward<Callable>(func)), DECAY_COPY (std::forward<Args>(args))...) 如果對func的這種調用拋出異常,則執行異常,否則返回。 異常執行應將異常傳播給call_once的調用者。 在任何給定的once_flagcall_once所有執行中:最多一個應該是返回執行; 如果有返回執行,則應該是最后一次執行; 只有在返回執行時才會執行被動執行。 [注意:被動執行允許其他線程可靠地觀察先前返回執行產生的結果。 - 尾注]

同步:對於任何給定的once_flag :所有活動執行都按總順序發生; 活動執行的完成與(1.10)該總訂單中下一個的開始同步; 並且返回的執行與所有被動執行的返回同步。

強調我的

這意味着對call_once所有調用都將等待,直到傳遞給call_once的函數完成。 在你的情況下,這意味着必須在任何線程調用print()之前調用do_once() print()

暫無
暫無

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

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