面试题答案
一键面试可能引发的问题
- 命名冲突:局部变量会隐藏全局变量,导致在局部作用域内无法直接访问全局变量,若不小心误用,可能导致程序逻辑错误。例如在多线程环境下,不同线程对同名变量的操作可能并非预期的全局变量操作。
- 数据竞争:如果多个线程同时访问和修改同名的局部变量和全局变量(特别是全局变量),可能导致数据竞争问题,使得程序结果不可预测,出现并发错误。
解决方案及分析
- 使用作用域解析运算符
::
访问全局变量:在局部作用域内,通过::
可以明确访问全局变量,避免命名冲突。
#include <iostream>
#include <thread>
int globalVar = 10;
void threadFunction() {
int globalVar = 20; // 局部变量与全局变量同名
std::cout << "局部变量 globalVar: " << globalVar << std::endl;
std::cout << "全局变量 globalVar: " << ::globalVar << std::endl;
}
int main() {
std::thread t(threadFunction);
t.join();
return 0;
}
- 使用互斥锁(Mutex):当涉及对全局变量的修改时,使用互斥锁可以避免数据竞争。互斥锁保证同一时间只有一个线程能访问被保护的资源(这里是全局变量)。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex globalMutex;
int globalVar = 10;
void threadFunction() {
std::lock_guard<std::mutex> lock(globalMutex);
globalVar++;
std::cout << "线程修改后的全局变量 globalVar: " << globalVar << std::endl;
}
int main() {
std::thread t1(threadFunction);
std::thread t2(threadFunction);
t1.join();
t2.join();
return 0;
}
- 线程局部存储(Thread - Local Storage, TLS):使用线程局部存储,每个线程都有自己独立的变量副本,避免了对全局变量的竞争。
#include <iostream>
#include <thread>
#include <mutex>
thread_local int localVar = 0;
void threadFunction() {
localVar++;
std::cout << "线程局部变量 localVar: " << localVar << std::endl;
}
int main() {
std::thread t1(threadFunction);
std::thread t2(threadFunction);
t1.join();
t2.join();
return 0;
}
在实际编程中,根据具体需求选择合适的方法。如果需要所有线程共享一个全局变量并保证其操作的原子性,使用互斥锁;如果每个线程需要有自己独立的变量副本,则使用线程局部存储。同时,注意合理命名变量,尽量避免局部变量与全局变量同名的情况。