Назад к вопросам
Middle
182
questionbank

Является ли std::shared_ptr потокобезопасным?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Нет. std::shared_ptr потокобезопасен для одновременного доступа к управляющему блоку (increment/decrement счетчика ссылок), но не для доступа к объекту, на который он указывает. Несколько потоков могут безопасно увеличивать или уменьшать счетчик ссылок одного std::shared_ptr одновременно. Однако, одновременный доступ к самому объекту, которым управляет std::shared_ptr, требует внешних механизмов синхронизации, таких как мьютексы.

Пример:

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

struct Data {
    int value;
    std::mutex mutex; // Добавляем мьютекс для синхронизации доступа к value
};

int main() {
    auto shared_data = std::make_shared<Data>();

    // Небезопасно: несколько потоков одновременно пишут в shared_data->value без синхронизации
    // auto unsafe_access = [&](int id) {
    //     for (int i = 0; i < 1000; ++i) {
    //         shared_data->value++;
    //     }
    // };

    // Безопасно: используем мьютекс для защиты доступа к shared_data->value
    auto safe_access = [&](int id) {
        for (int i = 0; i < 1000; ++i) {
            std::lock_guard<std::mutex> lock(shared_data->mutex); // Захват мьютекса
            shared_data->value++;
        }
    };

    std::vector<std::thread> threads;
    for (int i = 0; i < 10; ++i) {
        threads.emplace_back(safe_access, i);
        // threads.emplace_back(unsafe_access, i); // Для демонстрации небезопасного доступа
    }

    for (auto& t : threads) {
        t.join();
    }

    std::cout << "Final value (safe): " << shared_data->value << std::endl; // Предполагаемое значение 10000

    // Если использовать unsafe_access, итоговое значение будет, скорее всего, меньше 10000
    // std::cout << "Final value (unsafe): " << shared_data->value << std::endl;

    return 0;
}