std::call_once vs std::mutex for thread-safe initialization

后端 未结 3 1128
南笙
南笙 2021-02-05 10:16

I\'m a bit confused about the purpose of std::call_once. To be clear, I understand exactly what std::call_once does, and how to use it. It\'

3条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-05 10:44

    If you read this you'll see that std::call_once makes no guarantee about data-races, it's simply a utility function for performing an action once (which will work across threads). You shouldn't presume that is has anything close to the affect of a mutex.

    as an example:

    #include 
    #include 
    
    static std::once_flag flag;
    
    void f(){
        operation_that_takes_time();
        std::call_once(flag, [](){std::cout << "f() was called\n";});
    }
    
    void g(){
        operation_that_takes_time();
        std::call_once(flag, [](){std::cout << "g() was called\n";});
    }
    
    int main(int argc, char *argv[]){
        std::thread t1(f);
        std::thread t2(g);
        t1.join();
        t2.join();
    }
    

    could print both f() was called and g() was called. This is because in the body of std::call_once it will check whether flag was set then set it if not then call the appropriate function. But while it is checking or before it set flag another thread may call call_once with the same flag and run a function at the same time. You should still protect calls to call_once with a mutex if you know another thread may have a data race.

    EDIT

    I found a link to the proposal for the std::call_once function and thread library which states that concurrency is guaranteed to only call the function once, so it should work like a mutex (y)

    More specifically:

    If multiple calls to call_once with the same flag are executing concurrently in separate threads, then only one thread shall call func, and no thread shall proceed until the call to func has completed.

    So to answer your question: yes, other threads will be blocked until the calling thread returns from the specified functor.

提交回复
热议问题