Ответ
В современном C++ есть несколько безопасных способов обмена данными между потоками:
- Атомарные операции (
std::atomic): Для простых типов данных (int, bool, указатели). Гарантируют отсутствие гонок данных без использования мьютексов.std::atomic<int> shared_counter{0}; // Поток 1: shared_counter.fetch_add(1, std::memory_order_relaxed); // Поток 2: int value = shared_counter.load(std::memory_order_acquire); - Мьютексы и условные переменные (
std::mutex,std::condition_variable): Для защиты критических секций и организации ожидания событий. - Очереди (
std::queue+ мьютекс илиstd::priority_queue): Классический шаблон "производитель-потребитель". - Каналы (
std::promise/std::future): Для однократной передачи результата или исключения из одного потока в другой. - Потокобезопасные контейнеры: Если используется сторонняя библиотека вроде Intel TBB или самостоятельно написанные обертки.
Пример: потокобезопасная очередь для обмена сообщениями:
#include <queue>
#include <mutex>
#include <condition_variable>
template<typename T>
class ThreadSafeQueue {
std::queue<T> queue_;
mutable std::mutex mutex_;
std::condition_variable cond_var_;
public:
void push(T value) {
std::lock_guard<std::mutex> lock(mutex_);
queue_.push(std::move(value));
cond_var_.notify_one();
}
T pop() {
std::unique_lock<std::mutex> lock(mutex_);
cond_var_.wait(lock, [this]{ return !queue_.empty(); });
T value = std::move(queue_.front());
queue_.pop();
return value;
}
};
// Использование: один поток push(), другой — pop().