MST

星途 面试题库

面试题:C++中std::shared_ptr在复杂多线程环境下的问题

假设有一个多线程程序,多个线程同时对一个std::shared_ptr进行读写操作,可能会遇到什么问题?如何解决这些问题?请结合代码示例说明。
21.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

可能遇到的问题

  1. 数据竞争:多个线程同时读写 std::shared_ptr 时,可能导致数据不一致。比如一个线程正在释放对象(shared_ptr 计数减为0),而另一个线程还在尝试访问该对象,这会导致悬空指针访问,引发未定义行为。

解决方法

  1. 使用互斥锁(std::mutex:通过互斥锁来保护对 std::shared_ptr 的访问,确保同一时间只有一个线程可以对其进行读写操作。

以下是使用互斥锁解决问题的代码示例:

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

std::mutex sharedPtrMutex;
std::shared_ptr<int> sharedData;

void readSharedData() {
    std::unique_lock<std::mutex> lock(sharedPtrMutex);
    if (sharedData) {
        std::cout << "Read data: " << *sharedData << std::endl;
    }
}

void writeSharedData() {
    std::unique_lock<std::mutex> lock(sharedPtrMutex);
    sharedData = std::make_shared<int>(42);
    std::cout << "Write data: " << *sharedData << std::endl;
}

int main() {
    std::thread readThread(readSharedData);
    std::thread writeThread(writeSharedData);

    readThread.join();
    writeThread.join();

    return 0;
}
  1. 使用原子操作的智能指针(std::atomic_shared_ptr:C++20引入了 std::atomic_shared_ptr,它提供了原子性的操作,能避免数据竞争问题。

以下是使用 std::atomic_shared_ptr 的代码示例:

#include <iostream>
#include <memory>
#include <atomic>
#include <thread>

std::atomic_shared_ptr<int> sharedData;

void readSharedData() {
    auto data = sharedData.load();
    if (data) {
        std::cout << "Read data: " << *data << std::endl;
    }
}

void writeSharedData() {
    sharedData.store(std::make_shared<int>(42));
    std::cout << "Write data: " << *sharedData.load() << std::endl;
}

int main() {
    std::thread readThread(readSharedData);
    std::thread writeThread(writeSharedData);

    readThread.join();
    writeThread.join();

    return 0;
}

在实际应用中,如果使用的是C++20及以上版本,优先考虑 std::atomic_shared_ptr,因为它不需要额外的锁机制,性能更高;如果是C++20以下版本,使用 std::mutex 来保护 std::shared_ptr 的访问。