Нет, они не являются ни атомами c, ни поточными, и их использование из нескольких потоков приведет к сбоям или несоответствиям данных. та же структура данных будет плохо масштабироваться при добавлении новых потоков. Это связано с тем, как аппаратное обеспечение работает в условиях параллелизма; кратко:
- Производительность памяти сильно зависит от кешей
- Некоторые уровни кеша зависят от ядра ЦП
- Запись в память означает ее загрузку исключительно в кеш текущего ядра
- Процесс перемещения его из кэша одного ядра для записи в него является дорогостоящим (штраф в цикле 60-100 баллов)
Вы можете использовать блокировку для достижения правильности . Для этого я не рекомендую работать с блокировкой напрямую, но вместо этого загляните в модуль, подобный OO::Monitors
, где вы можете инкапсулировать ha sh в объект и выполнить блокировку на границах.
Если количество нажатий, которые вы делаете в общей структуре данных, мало по сравнению с объемом работы, проделанной для создания элементов в pu sh, то вы можете не ограничиваться блокировкой и конфликтом вокруг структуры данных. Однако, если вы выполняете тысячи push
или аналогичных операций в секунду, я предлагаю поискать альтернативный дизайн. Например:
- Разбейте работу на части для каждого работника
- Используйте
start
, чтобы выделить каждого работника, который возвращает Promise
. Поместите Promise
s в массив. - Пусть каждый
Promise
возвращает массив или ха sh произведенных им элементов. - Объедините результаты каждого из них. Например, если каждый возвращает массив, то
my @all-results = flat await @promises;
или аналогичного ему достаточно, чтобы собрать все результаты вместе.
Вы можете обнаружить, что ваша проблема хорошо вписывается в парадигму параллельного итератора , используя гипер или расу , в этом случае вам даже не нужно разбивать работу или настраивать работников самостоятельно; вместо этого вы можете выбрать степень и размер пакета.