Может ли несколько потоков обращаться к вектору в разных местах?

Предположим, что у меня есть вектор int, который я предварительно заполнил 100 элементами со значением 0.

Затем я создаю 2 потока и скажу первому потоку, чтобы заполнить элементы с 0 по 49 цифрами, а затем сообщите нитку 2, чтобы заполнить элементы с 50 по 99 номерами. Это можно сделать? В противном случае, какой лучший способ достичь этого?

Спасибо

Ответ 1

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

Ответ 2

Да, для большинства реализаций вектора это должно быть хорошо. Тем не менее, это будет иметь очень низкую производительность в большинстве систем, если у вас нет очень большого количества элементов, и вы получаете доступ к элементам, которые далеко друг от друга, так что они не живут в одной и той же строке кэша... иначе, во многих системах эти два потока будут недействительными друг к другу кэшировать назад и вперед (если вы часто читаете/записываете эти элементы), что приводит к большому количеству промахов в обоих потоках.

Ответ 3

Тот факт, что "vector не является потокобезопасным", ничего не значит. Нет проблем с этим.

Также вам не нужно выделять свой вектор в кучу (как один из предложенных ответов). Вам просто нужно убедиться, что продолжительность жизни вашего вектора охватывает время жизни ваших потоков (точнее - где эти потоки обращаются к вектору).

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

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

Простыми словами - нет проблем с доступом к массиву из разных потоков. Доступ к одному и тому же элементу из другого потока - это доступ к одной переменной из разных потоков - такие же меры предосторожности/последствия.

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

Ответ 4

Нет причин, по которым это невозможно сделать. Но, как только вы начинаете смешивать обращения (оба потока обращаются к одному и тому же элементу), он становится намного сложнее.

Ответ 5

vector не является потокобезопасным. Вам нужно защитить вектор между потоками. В вашем случае это зависит от реализации vector. Если входные внутренние данные доступны\изменены из разных потоков, это зависит исключительно от векторного impl.

Ответ 6

С массивами это можно сделать точно (потоки не имеют доступа к одной и той же области памяти); но, как уже отмечалось, если вы используете класс std::vector, результат может зависеть от того, как он реализован. В самом деле, я не вижу, как реализация [] в векторном классе может быть небезопасной (если потоки пытаются получить доступ к различным "индексам" ), но это может быть так. Решение: придерживаться использования массива или управлять доступом к вектору с помощью семафора или аналогичного.

Ответ 7

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

Ответ 8

То, что вы описываете, вполне возможно, и должно быть просто прекрасно.

Обратите внимание, однако, что потоки должны будут работать с std::vector*, то есть с указателем на исходный вектор --- и вы, вероятно, должны выделить вектор в куче, а не в стеке. Если вы передадите вектор напрямую, будет вызываться конструктор копирования и создать отдельную копию данных для каждого потока.

Есть также много более тонких способов сделать это неправильно, как всегда с многопоточным программированием. Но в принципе то, что вы описали, будет хорошо работать.