C++11中Lambda获取静态对象是否安全?instA1与instA2线程安全性分析
从Lambda获取静态对象是否安全?
咱们先把问题和代码理清楚,再结合C++11的标准规则来拆解分析:
问题背景
已知A::init()并非线程安全函数,在多线程场景下分别调用instA1()和instA2()获取单例,需要判断两者的线程安全性。
代码示例
// 存在线程安全问题的实现 A& instA1() { static A a; a.init(); return a; } // 待分析的实现(注:原代码中`A a = new A();`存在编译错误,已修正为合法写法) A& instA2() { static A a = [](){ A a; a.init(); return a; }(); return a; }
多线程调用场景
// thread1 A& a1 = instA1(); A& a2 = instA2(); // thread2 A& a1 = instA1(); A& a2 = instA2();
核心规则:C++11的静态局部变量初始化
C++11标准明确规定:函数内的静态局部变量,会在第一次被调用时完成初始化,且这个初始化过程是线程安全的。编译器会自动生成互斥同步逻辑,保证只有一个线程能执行初始化操作,其他线程会阻塞等待初始化完成后再继续执行。
对instA1的分析
instA1()的问题非常明确:
- 静态变量
a的默认构造是线程安全的(符合上面的规则); - 但每次调用
instA1()都会执行a.init(),而A::init()不是线程安全的。当多个线程同时调用instA1()时,会同时进入a.init()的执行逻辑,触发竞态条件,导致线程安全问题。
对instA2的分析
instA2()的设计刚好规避了instA1的问题:
- 静态变量
a的初始化依赖于lambda表达式的返回值,整个lambda的执行属于静态变量初始化的一部分; - 根据C++11的线程安全初始化规则,这个lambda只会被一个线程执行一次,其他线程会等待lambda执行完成(也就是
A对象创建+init()调用完成)后,才能获取到a的引用; - 这意味着
a.init()只会被调用一次,且是在单线程环境下执行,完全不会出现多线程同时调用init()的情况。
结论
在C++11标准下,instA2()是线程安全的,而instA1()存在线程安全问题。
内容的提问来源于stack exchange,提问作者lin
相关产品推荐
相关产品推荐

