Подтвердить что ты не робот

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

Если каждому потоку гарантируется только чтение/запись в конкретное подмножество массива, можно использовать несколько потоков для одного и того же (статического) массива, не прибегая к критическим разделам и т.д.?

РЕДАКТИРОВАТЬ. Это относится к конкретному случаю массивов типов без ссылки и записи/упакованных записей.

Если да, любые оговорки?

Чувство кишки да, но моя кишка иногда может быть ненадежным источником информации.

4b9b3361

Ответ 1

Предположим, что:

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

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

Ответ 2

Нет, в некоторых ситуациях это не может быть потокобезопасным.

Я вижу по крайней мере две причины.

1. Это будет зависеть от содержимого статического массива.

Если вы используете некоторые подсчитанные типы без ссылок (например, double, integer, bytes, shortstring), в большинстве случаев не будет никакой проблемы (по крайней мере, если данные прочитаны/только).

Но если вы используете некоторые типы с подсчетом ссылок (например, string, interface или вложенный динамический массив), вам нужно будет заботиться о безопасности потоков.

То есть:

TMyType1: array[0..1] of integer; // thread-safe on reading
TMyType2: array[0..1] of string;  // may be confusing

Дополнительное примечание: если ваш string на самом деле разделен между некоторыми частями статического массива, вы можете слить счетчик ссылок. Если вы явно не назовете UniqueString() для каждого из них (внутри критического раздела, я подозреваю). Для массива double или integer у вас не будет этой проблемы.

2. Это будет зависеть от доступа concurrency

Чтение доступа должно быть потокобезопасным даже для ссылочного подсчитанного типа, но одновременная запись может быть запутанной. Для string у вас могут быть проблемы с GPF в некоторых случайных случаях, особенно на многоядерном процессоре.

Некоторая безопасная реализация может быть:

  • Используйте критические разделы (как можно меньше, чтобы уменьшить накладные расходы) или другие структуры защиты;
  • Используйте Copy-On-Write или конфиденциальную копию содержимого для каждого потока.
  • Последнее примечание (не о безопасности, но о производительности). Совместное использование массива среди нескольких процессоров может привести к штрафам за производительность из-за синхронизации кеша между CPU. Производительность иногда намного лучше, когда вы используете разделенные массивы, гарантируя, что их кеширование L1 не будет разделяться между процессорами.

Помните, что такие проблемы могут быть кошмаром для отладки на стороне клиента: проблемы с несколькими нитями concurrency могут возникать случайным образом, и их очень сложно отслеживать. Чем безопаснее, тем лучше, если у вас нет явных и доказанных проблем с производительностью.

Дополнительное примечание. Для вашего конкретного случая статического массива double, с частью части массива, к которой обращается только один поток, он является потокобезопасным. Но нет абсолютного правила безопасности потоков во всех ситуациях, даже для статического массива. Как только вы используете некоторые типы подсчета ссылок или некоторые указатели, у вас могут быть случайные проблемы.