Один атом против нескольких ссылок
Каковы компромиссы представления состояния с использованием одного атома и хэш-карты против нескольких ссылок?
Например:
(def start (atom {:location "Chicago" :employer "John"}))
против
(def location (ref "Chicago"))
(def employer (ref "John"))
Большое спасибо
3 ответа
Версия с одним атомом лучше и имеет меньше компромиссов. Учитывая, что вы не хотите менять работодателя и местоположение не скоординировано, вы выигрываете в том, что вам не нужно создавать dosync
блок, чтобы изменить или местоположение или работодателя или обоих. Используя атом, вы можете просто (swap! start assoc :location "baz")
,
Большим компромиссом использования нескольких ссылок является то, что все транзакции с ссылками будут пробоваться параллельно, и выигрывает тот, кто готов, остальные перезапускаются. Хотя это также верно для атомов, наличие большего количества ссылок для всех записей требует большего мониторинга, группировки (для блоков досинхронизации) и т. Д. За кулисами. Чтобы было меньше перезапусков, имеет смысл сгруппировать информацию в хэш-карту. В зависимости от того, требуется ли согласованное изменение, поместите его в ссылку или атом.
Множественные ссылки допускают больше параллелизма, поскольку все записи в Atom линеаризуются. STM позволяет совершать много параллельных транзакций, когда нет конфликтующих записей / ensure
с (и дополнительно это обеспечивает commute
что позволяет делать определенные записи, которые обычно приводят к тому, что конфликт не делает этого).
Кроме того, STM взаимодействует с агентами - действия, отправленные агентам из транзакции, будут выполняться тогда и только тогда, когда транзакция зафиксирована. Это позволяет безопасно вызывать побочные эффекты изнутри транзакции. Атомы не предлагают аналогичного объекта.
Компромисс в том, что издержки STM больше, чем у Atom, плюс есть вероятность возникновения определенных аномалий (перекос записи, см. Страницу Википедии об изоляции моментальных снимков). Кроме того, можно добиться отличного параллелизма с STM, одновременно имея серьезные проблемы с получением снимка всей системы; в связи с этим, см. отличный пост в блоге Кристофа Гранда и его библиотеку megaref.
Во многих сценариях люди считают, что достаточно просто сохранить все состояния в одном Atom, и это, безусловно, более простой и более легкий подход.
Я не думаю, что вы должны думать о компромиссах между atoms
против refs
, поскольку они используются для разных ситуаций.
Вы должны использовать atom
когда вы хотите изменить одну вещь атомарно.
refs
использовать STM и вовлекать в транзакцию множество разных вещей, которые меняются одновременно.
В вашей конкретной ситуации вы должны отвечать на вопрос о том, что вы меняете.
- Это одна вещь, которую вы хотите / можете изменить за один шаг
- Являются ли разные вещи, которые вы хотите / нужно изменить транзакционно
Если вы переключите старую базу данных на новую и измените все вместе, чтобы изменить одно поле, и вы скажете, что ваша база данных является atom
Ты злоупотребляешь механизмом.
Надеюсь, что различие помогает, для вашего примера я бы использовал атом, тем не менее.
Здесь есть хорошее резюме с мотивами каждой стратегии.