Что значит сделать динамический массив потокобезопасным и параллельным? Скажите, например, std::vector
.
- Два потока могут захотеть вставить в одну и ту же позицию. Синхронизация не требуется, так как она будет выполняться в соответствии с расписанием потоков.
- Один поток стирается, а другой собирается получить доступ к одному и тому же элементу? Я считаю, что это не проблема структуры данных, это проблема использования.
Итак, нужно ли что-нибудь сделать над std::vector
, чтобы сделать его потокобезопасным и параллельным, или он по умолчанию является потокобезопасным и параллельным?
2 ответа
C ++ 11 говорит следующее о потокобезопасности контейнеров в стандартной библиотеке:
23.2.2 Гонки данных контейнеров [container.requirements.dataraces]
Во избежание гонок данных (17.6.5.9) реализации должны считать следующие функции константами:
begin
,end
,rbegin
,rend
,front
,back
,data
,find
,lower_bound
,upper_bound
,equal_range
,at
и, кроме ассоциативных или неупорядоченные ассоциативные контейнеры,operator[]
.Несмотря на (17.6.5.9), реализации должны избегать данных гонки, когда содержимое содержащегося объекта в разных элементах в той же последовательности, за исключением
vector<bool>
, изменяются одновременно.
Таким образом, в основном чтение из контейнера из нескольких потоков - это нормально, а изменение элементов, которые уже находятся в контейнере, - это нормально (если они являются разными элементами).
Итак, ни один из ваших двух конкретных вопросов не является потокобезопасным для std::vector
:
1) Два потока, вставляемые в вектор, изменяют сам вектор, а не существующие отдельные элементы.
2) Стирание одного потока и другие попытки доступа к одному и тому же элементу небезопасны, потому что стирание элемента из вектора не является операцией, которая обещает быть поточно-безопасной (или «свободной от гонок данных», как сказано в стандарте). .
Для безопасного выполнения этих операций потребуется, чтобы программа сама выполняла некоторую внешнюю синхронизацию.
[]
в векторе, чтобы получить элемент с индексом X, поток прерывается сразу после начала вызова, а другой поток вставляет новый элемент. перед индексом X. Тогда начальный поток все равно получит элемент с индексом X, но это могут быть не те данные, которые ожидал поток.
atomic
. Но обратите внимание, что atomic<T>
не имеет конструктора копирования, поэтому невозможно использовать какие-либо функции, которые проверяют, должны ли они увеличивать вектор, независимо от шагов, которые вы предпринимаете, чтобы убедиться, что он не нужен расти. Код из неиспользованных веток по-прежнему требуется для компиляции на C ++. Как объявить атомарный вектор в C ++) . Это по-прежнему не делает безопасным изменение самого контейнера, а только его элементы.
Единственные параллельные операции над одним объектом в стандартной библиотеке, которые по умолчанию безопасны: - Доступ только к const
- функциям-членам - Все обращения к примитивам синхронизации (например, блокировка и разблокировка мьютекса или атомарные операции) Все остальное необходимо синхронизировать извне. В частности, в стандартной библиотеке пока нет потоковобезопасных контейнеров (начиная с C ++ 14).
Итак, ответ на оба ваших примера - нет, они оба требуют внешней синхронизации.
Что вы, конечно, можете сделать, так это изменить значение двух разных элементов в контейнере.
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.
std::vector
- один), - это чтение . Как только вы вводите потенциал для одновременной операции записи на одном и том же объекте внутри, колеса начинают падать, и если сами объекты не поддерживают атомарные обновления в этом сценарии, колеса покинули транспортное средство. . И если сам контейнер подвергнется какой-либо механике, потенциально изменяющей компоновку, колеса уже будут в четверти мили позади вас в канаве.