C++11 Потокобезопасность конструкторов копирования std::atomic‹T›

У меня были проблемы с атомарным контейнером, и я увидел эту ссылку.

Есть ли причина, по которой std::atomic нельзя скопировать? Решение кажется это, где они просто передают значение T неатомарному конструктору с функцией атомарной загрузки (если я не ошибаюсь).

Итак, в целом, является ли этот конструктор копирования потокобезопасным?

template<typename T>
struct MobileAtomic
{
    std::atomic<T> atomic;

    explicit MobileAtomic(std::atomic<T> const& a) : atomic(a.load()) {}

};

person JohnJohn    schedule 06.01.2015    source источник
comment
Неясно, достигает ли этот код чего-либо разумного. Атомики служат очень специфической цели, и обычно нет смысла их копировать.   -  person Kerrek SB    schedule 06.01.2015
comment
В качестве аналогии: атомарный int гораздо ближе к мьютексу или семафору, чем к целому числу. Вы можете запросить текущее состояние семафора (которое соответствует атомарной загрузке), но нет смысла копировать сам семафор. Это механизм синхронизации и создание копии, если это нецелесообразно.   -  person Kerrek SB    schedule 06.01.2015
comment
Мне также не ясно, что означает, что конструктор должен быть потокобезопасным. Кто что строит общим способом?   -  person Kerrek SB    schedule 06.01.2015
comment
Ну, если вы должны вернуть атомарную переменную по значению в функции, я думаю, она неявно пытается вызвать конструктор копирования. Компилятор выдает мне ошибку, указывающую на это объявление конструктора atomic& operator=(const atomic&) = delete;, которое в основном запрещено C++. Я предполагаю, что возврат ссылки на переменную сделает то же самое, но я не уверен.   -  person JohnJohn    schedule 06.01.2015
comment
Для функции нет абсолютно никакого смысла возвращать атомарную переменную. Точно так же, как функции нет смысла возвращать мьютекс.   -  person Kerrek SB    schedule 06.01.2015


Ответы (1)


Есть ли причина, по которой std::atomic нельзя построить с помощью копирования?

Да.

Когда вы запрашиваете конструируемую копию atomic, вы просите, чтобы «обычные» правила однопоточной последовательной согласованности применялись к переменной, которая не следует этим правилам.

По сути, универсального решения нет.

Используя конструктор, показанный в вопросе, вы жертвуете детерминированным результатом, поскольку у вас нет гарантии, что исходный и конечный объекты эквивалентны после завершения построения.

person Michael Gazonda    schedule 06.01.2015
comment
Мне кажется, у меня есть только два варианта: я могу вернуть значение атомарной переменной только по значению (которое может измениться другим потоком, пока значение не будет присвоено caller = race), либо вернуть ссылку на атомарную переменную ( это переменная, которую я не хочу раскрывать). Я предполагаю, что мой лучший вариант - вернуть ссылку на константу, которую я еще не пробовал. - person JohnJohn; 06.01.2015
comment
@JohnJohn Другой вариант - заблокировать переменную мьютексом на время чтения. - person Michael Gazonda; 06.01.2015
comment
@JohnJohn: Вы можете этого не осознавать, но как только вы сделаете копию, значение исходного объекта может отличаться от значения копии. это не состояние гонки. Это нормальное поведение, когда у вас есть две переменные. Если логически у вас есть одно значение, у вас должен быть один объект. - person MSalters; 06.01.2015
comment
@JohnJohn Я написал много параллельного кода без блокировки на разных языках, и я не могу вспомнить ни одного примера, в котором я хотел бы скопировать атомарную переменную. Вероятно, вам следует задать вопрос о том, что вы действительно пытаетесь сделать, и посмотреть, нет ли лучшего способа решить эту проблему. - person Voo; 06.01.2015
comment
@Voo, пример, над которым я работал, - это std::atomic<void*> foo, где foo может изменить то, на что он указывает, и у меня есть отдельные механизмы для поддержания времени жизни и параллелизма этих данных, на которые указывает foo. Случай будет обрабатываться атомарным shared_ptr, но я хотел бы придерживаться стандартных библиотечных решений (из которых не существует атомарного общего ptr). - person Noah Watkins; 03.07.2017