MST

星途 面试题库

面试题:C++函数指针在多线程环境下回调的注意事项

在多线程环境中使用C++函数指针实现回调机制,会面临哪些问题?如何解决这些问题?请结合代码示例进行说明。
29.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

面临的问题

  1. 线程安全问题:多个线程同时调用函数指针指向的回调函数时,可能会出现竞争条件,导致数据不一致。例如,如果回调函数访问和修改共享资源,不同线程的操作顺序可能会导致结果不可预测。
  2. 内存管理问题:如果函数指针所指向的回调函数对象在某个线程中被释放,但其他线程仍持有该函数指针并尝试调用,就会导致悬空指针,引发程序崩溃。

解决方法

  1. 线程安全
    • 使用互斥锁(std::mutex)来保护共享资源。在访问共享资源前锁定互斥锁,访问结束后解锁。
    • 使用线程局部存储(thread_local)来避免共享资源竞争,每个线程都有自己独立的变量副本。
  2. 内存管理
    • 使用智能指针(如std::unique_ptrstd::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;
}

在上述代码中:

  1. 线程安全CallbackClass中的callbackFunction使用std::lock_guard<std::mutex>来确保在多线程环境下对共享资源(这里主要是输出操作)的安全访问。
  2. 内存管理:通过std::unique_ptr<CallbackClass>来管理CallbackClass对象的生命周期,保证对象在所有线程使用完毕后才被释放。在threadFunction中,通过检查callbackObj是否为空来避免悬空指针调用。