C++11以后,使用局部变量懒汉为什么不用加锁
时间: 2024-09-15 15:15:15 浏览: 62
c++作用域运算符用法(全局变量和局部变量)
5星 · 资源好评率100%
C++11之后引入了一些新的特性和技术,使得在某些特定情况下,使用局部变量实现的懒汉式单例模式在首次访问时不需要额外的锁保护,通常是因为以下几个原因:
1. **`std::once_flag` 和 `std::call_once`**:C++11引入了`std::once_flag`和`std::call_once`函数对初始化操作进行了封装,这是用于确保初始化操作仅执行一次的标准库机制。当你第一次尝试获取实例时,会检查是否已初始化,如果没有则执行初始化并设置标志,后续线程将不会再次初始化,所以无需锁。
```cpp
class Singleton {
private:
std::once_flag flag;
static Singleton* instance;
public:
Singleton() = default;
static Singleton& getInstance() {
std::call_once(flag, []() { instance = new Singleton(); });
return *instance;
}
};
```
这里的`std::call_once`内部会自动确保线程安全。
2. **编译器优化**:现代编译器如GCC、Clang等能够对这类代码进行分析,识别出这种“惰性”初始化模式,然后在编译阶段对其进行优化,确保单例只初始化一次。
3. **线程局部存储(TLS)**:对于局部变量,编译器通常会将其存储在每个线程的私有区域,这在大多数情况下意味着它们是线程私有的,互不影响。因此,在第一次请求时,实例会在本线程中初始化,不需要全局锁。
然而,尽管如此,对于并发性能要求极高的应用,还是建议使用更高级的线程安全策略,比如上面提到的双重检查锁定或基于原子指令的方案。
阅读全文