static线程安全
在 C++ 中,静态变量(static variables) 在多线程环境下需要特别注意 线程安全,因为它们被所有线程共享。以下是不同场景下的使用示例及最佳实践:
1. 全局静态变量(线程安全需加锁)
#include <iostream>
#include <thread>
#include <mutex>// 全局静态变量(所有线程共享)
static int sharedCounter = 0; // 所有线程共享的静态变量
static std::mutex mtx; // 互斥锁保护共享变量void incrementCounter() {for (int i = 0; i < 1000; ++i) {std::lock_guard<std::mutex> lock(mtx); // 在构造时锁定 mtx,析构时自动解锁(即使发生异常也会解锁)。sharedCounter++; // 安全修改} //作用域结束时(}),lock 对象析构,释放锁。
}int main() {std::thread t1(incrementCounter); // 启动线程1std::thread t2(incrementCounter); // 启动线程2t1.join(); // 等待线程1结束t2.join();// 等待线程2结束std::cout << "Final counter value: " << sharedCounter << std::endl; // 应为 2000return 0;
}
关键点:
使用 std::mutex 保护共享静态变量,避免竞态条件。
std::lock_guard 在作用域结束时自动释放锁。
2. 局部静态变量(延迟初始化需线程安全)
如果静态变量在函数内部(需要延迟初始化),C++11 起保证其初始化是线程安全的:
#include <iostream>
#include <thread>void initStaticVar() {static int lazyInitialized = 42; // C++11 起线程安全初始化std::cout << "Value: " << lazyInitialized << std::endl;
}int main() {std::thread t1(initStaticVar);std::thread t2(initStaticVar);t1.join();t2.join();return 0;
}
注意:
C++11 前需手动加锁(如 pthread_once)。
修改 lazyInitialized 仍需额外同步。
3. 静态类成员变量(需外部定义)
#include <iostream>
#include <thread>
#include <mutex>class MyClass {
public:static int classVar; // 声明static std::mutex mtx;static void modifyClassVar() {std::lock_guard<std::mutex> lock(mtx);classVar++;}
};// 必须在类外定义静态成员
int MyClass::classVar = 0;
std::mutex MyClass::mtx;int main() {std::thread t1(&MyClass::modifyClassVar);std::thread t2(&MyClass::modifyClassVar);t1.join();t2.join();std::cout << "Final classVar: " << MyClass::classVar << std::endl; // 应为 2return 0;
}
规则:
静态类成员需在类外单独定义(链接器需要实际存储)。
修改时同样需要加锁。
4. 线程局部静态变量(C++11 thread_local)
如果希望每个线程有独立的静态变量副本:
#include <iostream>
#include <thread>void threadLocalStatic() {thread_local static int localCounter = 0; // 每个线程独立localCounter++;std::cout << "Thread " << std::this_thread::get_id() << ", localCounter: " << localCounter << std::endl;
}int main() {std::thread t1([](){threadLocalStatic();threadLocalStatic(); // 输出 1, 2});std::thread t2([](){threadLocalStatic(); // 输出 1});t1.join();t2.join();return 0;
}