std :: call_once调用的可调用函数将挂起,如果它试图在同一个std :: once_flag上调用std :: call_once

时间:2017-04-20 11:38:56

标签: c++11

我遇到了由此行为导致的错误:

#include <mutex>

std::once_flag onceFlag;

void get() {
    std::call_once(onceFlag, [](){ get(); });
}

int main(int argc, char* argv[]) {
    get();
    return 0;
}

另一种方式是:

#include <mutex>

std::once_flag onceFlag;

int main(int argc, char* argv[]) {
    std::call_once(onceFlag,
        [](){
            std::call_once(onceFlag,
                [](){}
            );
        }
    );

    return 0;
}

根据我在cppreference(http://en.cppreference.com/w/cpp/thread/call_once)上所读到的内容,这是可以预料的,因为第一次调用std :: call_once还没有完成执行:

  

在上述之前,组中没有调用返回   成功完成所选功能的执行,即   不会通过例外退出。

为什么上述要求?在调用函数之前是否可以设置once_flag,如果抛出异常则重置?

1 个答案:

答案 0 :(得分:2)

  

为什么上述要求?之前不能设置once_flag   调用该函数,如果抛出异常则重置?

没有。在您的提案中,once_flag将被设置,然后在发生任何故障时重置。这可能会造成竞争条件。考虑具有2个线程的这种情况:th1th2。两者都在做一些任务,需要完成一次。线程依赖once_flag在您的提案中工作。 th1内部功能由once_flag保护。 th2正在检查once_flag条件并停止执行,因为它的pov任务已完成。在任务执行期间,th1抛出异常,从th1 pov它很好,因为其他一些工作人员将完成执行。任务永远不会完成,因为th1失败并且once_flag未设置,但th2已完成,因为once_flag已设置,并且它认为任务已完成。

根据当前的要求,不会发生这种不一致。