Является ли shared_ptr потокобезопасным и можно ли использовать его в контексте нескольких потоков?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Да, shared_ptr потокобезопасен для операций инкремента/декремента счетчика ссылок. Это означает, что множество потоков могут одновременно копировать или уничтожать shared_ptr к одному и тому же ресурсу без гонки данных на самом счетчике.
Однако доступ к управляемому объекту данных через несколько shared_ptr из разных потоков не является потокобезопасным по умолчанию. Если разные потоки читают и/или модифицируют этот объект одновременно, вам необходимо использовать дополнительные механизмы синхронизации (например, мьютексы) для защиты самого объекта.
Использование shared_ptr в многопоточном контексте возможно и часто необходимо, но требует понимания того, какая часть shared_ptr (счетчик) потокобезопасна, а какая (доступ к данным) — нет.
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
#include <mutex> // Для синхронизации доступа к данным
struct Data {
int value;
std::mutex mutex; // Мьютекс для защиты value
Data(int v) : value(v) {}
};
int main() {
auto shared_data = std::make_shared<Data>(0);
auto increment = [&](std::shared_ptr<Data> ptr) {
// Доступен из разных потоков - счетчик ссылок потокобезопасен
std::lock_guard<std::mutex> lock(ptr->mutex); // Защита доступа к value
ptr->value++;
};
std::vector<std::thread> threads;
int num_threads = 10;
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back(increment, shared_data); // Передача копии shared_ptr
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final value: " << shared_data->value << std::endl; // Должно быть 10
return 0;
}