Один атом против нескольких ссылок

Каковы компромиссы представления состояния с использованием одного атома и хэш-карты против нескольких ссылок?

Например:

(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Ты злоупотребляешь механизмом.

Надеюсь, что различие помогает, для вашего примера я бы использовал атом, тем не менее.

Здесь есть хорошее резюме с мотивами каждой стратегии.

Другие вопросы по тегам