send
и send-off
добавляют функции в очереди для агента и немедленно возвращаются.Таким образом, из-за их асинхронного характера они не могут зайти в тупик.
Однако рабочий пул, используемый send
, предназначен для вычислительной работы и, таким образом, имеет фиксированный размер пула (2 + число ядер).Если вы (неправильно) вызовете send
с задачей, которая может заблокировать ввод-вывод или что-то еще, эта задача заблокирует одно из фиксированного числа потоков процессора в пуле.Если бы вы делали это одновременно с (2 + # ядрами) задачами, вы могли бы эффективно блокировать пул потоков процессора.Конечно, решение состоит в том, чтобы использовать вместо него правильный send-off
.Рабочий пул, используемый send-off
, неограничен.
При отправке в действии страница агентов сообщает:
Если во время выполнения функции любой другойотправления производятся (прямо или косвенно), они будут удерживаться до тех пор, пока состояние агента не будет изменено.
Когда отправка происходит в конце агента, отправка помещает элемент вочередь отправки и немедленно возвращается.Поскольку агенты никогда не блокируют ожидание ресурса, невозможно создать цикл взаимоблокировки.
Также нет возможности для гонки данных - состояние агента должно быть неизменным Clojureданные.Агент применяет функцию изменения в посылке и атомарно заменяет состояние агента.Считыватели (через dereference
или @
) видят стабильное значение в какой-то момент времени жизни агента.Если вам нужна координация читателей и писателей, вы должны использовать refs .
Существует возможность условия гонки : два вызова send
из разных потоковможет ли "гонка" быть помещенной в очередь агента, а также одновременно читающие могут воспринимать различные (стабильные) значения в зависимости от того, когда они читают временную шкалу агента.Однако это характер асинхронных вычислений.Если вы хотите скоординированные вычисления при чтении или записи нескольких ресурсов, вы должны использовать refs .