面试题答案
一键面试sharedGlobal
初始化面临的问题及解决方案
- 竞争条件:多个线程可能同时尝试初始化
sharedGlobal
,导致重复初始化或部分初始化的问题。- 解决方案:使用互斥锁(
std::mutex
)。在初始化sharedGlobal
前加锁,初始化完成后解锁。例如:
- 解决方案:使用互斥锁(
#include <mutex>
std::mutex globalMutex;
int sharedGlobal;
void initializeSharedGlobal() {
std::lock_guard<std::mutex> lock(globalMutex);
if (!sharedGlobal) {
sharedGlobal = 42;
}
}
- 数据一致性:如果在一个线程初始化
sharedGlobal
时,其他线程开始使用它,可能会读到未初始化或部分初始化的数据。- 解决方案:使用
std::once_flag
和std::call_once
。std::call_once
确保函数只被调用一次,无论多少线程尝试调用。例如:
- 解决方案:使用
#include <mutex>
#include <memory>
std::once_flag globalFlag;
int sharedGlobal;
void initializeSharedGlobal() {
sharedGlobal = 42;
}
void accessSharedGlobal() {
std::call_once(globalFlag, initializeSharedGlobal);
// 使用sharedGlobal
}
threadLocal
初始化面临的问题及解决方案
- 每个线程独立初始化:每个线程都需要有自己独立的
threadLocal
变量实例,并且初始化过程不能相互干扰。- 解决方案:利用C++11的线程局部存储(TLS)。通过在变量声明前加上
thread_local
关键字来声明线程局部变量。例如:
- 解决方案:利用C++11的线程局部存储(TLS)。通过在变量声明前加上
thread_local int threadLocal = 0;
这样每个线程都有自己独立的threadLocal
变量实例,其初始化不会受到其他线程影响。
利用C++11线程局部存储(TLS)优化局部变量在多线程中的初始化和使用
- 初始化优化:
thread_local
变量的初始化在每个线程第一次使用该变量时进行,且只初始化一次。这种延迟初始化特性避免了不必要的初始化开销,特别是当线程可能不会用到该变量时。 - 使用优化:由于每个线程有自己独立的实例,访问
thread_local
变量不需要额外的同步机制,提高了访问效率,同时保证了线程安全。例如:
#include <iostream>
#include <thread>
thread_local int threadLocal = 0;
void threadFunction() {
++threadLocal;
std::cout << "Thread " << std::this_thread::get_id() << " has threadLocal value: " << threadLocal << std::endl;
}
int main() {
std::thread t1(threadFunction);
std::thread t2(threadFunction);
t1.join();
t2.join();
return 0;
}
在上述代码中,每个线程独立地修改和访问自己的threadLocal
变量,无需额外同步。