面试题答案
一键面试面临的问题
- 线程安全问题:多个线程同时调用函数指针指向的回调函数时,可能会出现竞争条件,导致数据不一致。例如,如果回调函数访问和修改共享资源,不同线程的操作顺序可能会导致结果不可预测。
- 内存管理问题:如果函数指针所指向的回调函数对象在某个线程中被释放,但其他线程仍持有该函数指针并尝试调用,就会导致悬空指针,引发程序崩溃。
解决方法
- 线程安全:
- 使用互斥锁(
std::mutex
)来保护共享资源。在访问共享资源前锁定互斥锁,访问结束后解锁。 - 使用线程局部存储(
thread_local
)来避免共享资源竞争,每个线程都有自己独立的变量副本。
- 使用互斥锁(
- 内存管理:
- 使用智能指针(如
std::unique_ptr
或std::shared_ptr
)来管理回调函数对象的生命周期,确保对象在所有线程都不再使用时才被释放。
- 使用智能指针(如
代码示例
#include <iostream>
#include <thread>
#include <mutex>
#include <memory>
class CallbackClass {
public:
void callbackFunction() {
std::lock_guard<std::mutex> lock(mutex_);
std::cout << "Callback function executed in thread " << std::this_thread::get_id() << std::endl;
}
private:
std::mutex mutex_;
};
void threadFunction(std::unique_ptr<CallbackClass>& callbackObj, void (CallbackClass::*callbackFunc)()) {
if (callbackObj) {
(callbackObj.get()->*callbackFunc)();
}
}
int main() {
std::unique_ptr<CallbackClass> callbackObj = std::make_unique<CallbackClass>();
void (CallbackClass::*callbackFunc)() = &CallbackClass::callbackFunction;
std::thread thread1(threadFunction, std::ref(callbackObj), callbackFunc);
std::thread thread2(threadFunction, std::ref(callbackObj), callbackFunc);
thread1.join();
thread2.join();
return 0;
}
在上述代码中:
- 线程安全:
CallbackClass
中的callbackFunction
使用std::lock_guard<std::mutex>
来确保在多线程环境下对共享资源(这里主要是输出操作)的安全访问。 - 内存管理:通过
std::unique_ptr<CallbackClass>
来管理CallbackClass
对象的生命周期,保证对象在所有线程使用完毕后才被释放。在threadFunction
中,通过检查callbackObj
是否为空来避免悬空指针调用。