面试题答案
一键面试1. 引用和指针在多线程异常处理中的挑战
- 线程安全问题:
- 指针:多个线程可能同时访问和修改同一个指针所指向的内存。例如,一个线程释放了指针指向的内存,而另一个线程仍在使用该指针,这就导致了悬垂指针问题,可能引发未定义行为。
- 引用:由于引用一旦初始化就不能重新绑定,在多线程环境下,如果引用所绑定的对象被其他线程意外销毁,也会导致类似悬垂指针的问题。
- 数据竞争:
- 指针:当多个线程对指针进行读写操作时,如果没有适当的同步机制,就会发生数据竞争。例如,一个线程正在修改指针指向的内容,另一个线程同时读取该内容,可能导致读取到不一致的数据。
- 引用:同样,对引用所绑定对象的并发读写操作,如果没有同步,也会产生数据竞争。
2. 通用异常处理策略思路
- 资源管理:使用智能指针(如
std::unique_ptr
和std::shared_ptr
)来管理动态分配的资源。智能指针会在其作用域结束时自动释放资源,避免手动释放带来的问题。 - 同步机制:使用互斥锁(
std::mutex
)、条件变量(std::condition_variable
)等同步工具来保护共享资源,防止数据竞争。 - 异常安全设计:确保函数在抛出异常时,不会导致资源泄漏或使程序处于不一致状态。遵循 “基本异常安全保证” 和 “强异常安全保证” 原则。
3. 伪代码示例
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
class SharedResource {
public:
SharedResource() { std::cout << "SharedResource created" << std::endl; }
~SharedResource() { std::cout << "SharedResource destroyed" << std::endl; }
void doWork() { std::cout << "Doing work on SharedResource" << std::endl; }
};
std::mutex resourceMutex;
std::shared_ptr<SharedResource> sharedResource;
void threadFunction() {
std::unique_lock<std::mutex> lock(resourceMutex);
if (!sharedResource) {
try {
sharedResource = std::make_shared<SharedResource>();
} catch (const std::exception& e) {
// 处理异常,例如记录日志
std::cerr << "Exception in creating SharedResource: " << e.what() << std::endl;
// 可以选择抛出异常或者进行其他处理
throw;
}
}
lock.unlock();
// 使用共享资源
try {
sharedResource->doWork();
} catch (const std::exception& e) {
// 处理使用资源时的异常
std::cerr << "Exception in using SharedResource: " << e.what() << std::endl;
}
}
int main() {
std::thread t1(threadFunction);
std::thread t2(threadFunction);
t1.join();
t2.join();
return 0;
}
在上述伪代码中:
- 使用
std::shared_ptr
来管理共享资源SharedResource
,确保资源在不再被使用时自动释放。 - 使用
std::mutex
来保护对sharedResource
的初始化操作,避免多个线程同时创建资源导致的数据竞争。 - 在每个可能抛出异常的操作周围使用
try - catch
块来捕获并处理异常,确保程序在异常发生时不会崩溃,并且资源能够得到正确管理。