自动捕获变量的静态lambda初始化是否同步,需要手动加互斥锁吗?
静态lambda初始化线程安全性解答
你给出的示例代码如下:
void f() { int i; static auto lambda = [&i]() { cout << &i << endl; }; // volatile to prevent inline-optimizations function<void()> fn( lambda ), *volatile pFn = &fn; (*pFn)(); }
针对你询问的静态lambda初始化是否同步、是否需要自行加mutex保护的问题,解答如下:
核心结论
在C++11及更高版本的标准环境下,该静态lambda的初始化过程天然同步、线程安全,不需要你额外使用mutex进行保护。
标准依据
C++11明确规定了函数作用域内静态局部变量的初始化规则:
- 静态局部变量仅会在执行流第一次到达其声明位置时完成初始化
- 初始化过程是线程安全的:多个线程同时首次触发该静态变量初始化时,仅一个线程会执行初始化逻辑,其余线程会阻塞等待初始化完成,不会出现初始化未完成就被访问的竞态条件
这个特性也被业内称为「魔法静态变量(Magic Static)」,目前所有主流C++编译器(GCC 4.3+、Clang 2.9+、MSVC 2010+)都已完整支持该特性。
额外说明
以上结论仅针对静态lambda的初始化过程本身的安全性,和你代码本身的逻辑缺陷无关:
该lambda按引用捕获的是第一次调用f()时栈上局部变量i的地址,后续调用f()时,栈上的局部变量i的地址会发生变化,lambda持有的引用实际上已经是野引用,访问会触发未定义行为,该问题需要你单独修复,和初始化的线程安全性没有关联。
如果你使用的是C++03及更早的标准,静态局部变量的初始化没有线程安全保证,此时才需要自行通过mutex保护初始化过程。
内容的提问来源于stack exchange,提问作者Bonita Montero
相关产品推荐
相关产品推荐

