MST

星途 面试题库

面试题:C++ std::weak_ptr 在多线程环境下的使用限制

在多线程环境中使用 std::weak_ptr 会面临哪些特殊的使用限制?请详细阐述,并给出一个多线程场景下正确使用 std::weak_ptr 避免相关问题的代码示例,同时分析可能出现的竞争条件及解决方法。
45.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

使用限制

  1. 对象可能已销毁std::weak_ptr 不增加对象引用计数,在多线程环境下,当通过 lock 方法尝试获取 std::shared_ptr 时,对象可能在其他线程已经被销毁,导致获取到空指针。
  2. 线程安全问题std::weak_ptr 本身的操作并非线程安全。例如,在一个线程中检查 weak_ptr 是否过期,同时另一个线程销毁了对象,可能会出现不一致的结果。

代码示例

#include <iostream>
#include <memory>
#include <thread>
#include <mutex>

std::mutex weakPtrMutex;
std::weak_ptr<int> weakObj;

void createObject() {
    std::shared_ptr<int> sharedObj = std::make_shared<int>(42);
    std::lock_guard<std::mutex> lock(weakPtrMutex);
    weakObj = sharedObj;
}

void accessObject() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    std::shared_ptr<int> sharedObj;
    {
        std::lock_guard<std::mutex> lock(weakPtrMutex);
        sharedObj = weakObj.lock();
    }
    if (sharedObj) {
        std::cout << "Accessed object: " << *sharedObj << std::endl;
    } else {
        std::cout << "Object has been destroyed." << std::endl;
    }
}

int main() {
    std::thread t1(createObject);
    std::thread t2(accessObject);

    t1.join();
    t2.join();

    return 0;
}

竞争条件及解决方法

  1. 竞争条件:在多线程环境下,可能出现一个线程在检查 weak_ptr 是否过期后,还未获取 shared_ptr 时,对象在其他线程被销毁。
  2. 解决方法
    • 使用互斥锁,如上述代码中通过 std::mutex 来保护对 weak_ptr 的操作,确保在同一时间只有一个线程能访问和修改 weak_ptr。这样可以避免多个线程同时操作 weak_ptr 导致的不一致问题。
    • 当获取 shared_ptr 后,及时检查其是否为空,防止对已销毁对象的悬空引用。