2017-04-20 70 views
1

我跑进造成这种行为的错误:通过的std :: call_once的调用的函数调用将挂起:: once_flag

#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,并且在抛出异常时重置?

+0

简答:因为委员会决定应该。 – Caleth

回答

2

为什么上述要求?在函数被调用之前,不能设置once_flag,并且在抛出异常时重置?

那么没有。在您的建议once_flag将被设置,然后在任何故障的情况下重新设置。这可能会造成竞争条件。考虑2线程的这种情况:th1和​​。两个人都在做一些任务,只需要完成一次。线程依赖once_flag按照您的建议进行工作。 th1在守护着once_flag的功能。​​正在检查once_flag条件并停止执行,因为从它的pov任务完成。在th1任务执行期间抛出异常,从th1 pov就可以了,因为其他一些worker会完成执行。任务从未完成,因为th1失败,并且once_flag未设置,但​​已完成,因为once_flag已设置,并且它假定任务已完成。

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