Пример компоновки программной транзакционной памяти


11

Одно из главных преимуществ программной транзакционной памяти, которое всегда упоминается, - это возможность компоновки и модульность. Различные фрагменты могут быть объединены для получения более крупных компонентов. В программах, основанных на блокировке, это часто не так.

Я ищу простой пример, иллюстрирующий это с помощью реального кода. Я бы предпочел пример в Clojure, но с Хаскеллом тоже все в порядке. Бонусные баллы, если в примере также показан некоторый код на основе блокировки, который не может быть легко составлен.


1
Интересно, но для меня это звучит больше как вопрос StackOverflow.
Стив

Этот вопрос был задан там через 4 минуты. stackoverflow.com/questions/5518546/… Будет ли кто-нибудь перенести и объединить этот вопрос (если это возможно)?
Работа

Да, после того, как я разместил это здесь, я понял, что, вероятно, будет лучше на Stackoverflow. Если кто-то может слить это, это нормально для меня.
dbyrne

Ответы:


9

Предположим, у вас есть несколько банковских счетов:

(def accounts 
 [(ref 0) 
  (ref 10) 
  (ref 20) 
  (ref 30)])

И атомная «передаточная» функция:

(defn transfer [src-account dest-account amount]
  (dosync
    (alter dest-account + amount)
    (alter src-account - amount)))

Который работает следующим образом:

(transfer (accounts 1) (accounts 0) 5)

(map deref accounts)
=> (5 5 20 30)

Затем вы можете легко составить функцию переноса, чтобы создать транзакцию более высокого уровня, например, перенос с нескольких учетных записей:

(defn transfer-from-all [src-accounts dest-account amount]
  (dosync
    (doseq [src src-accounts] 
      (transfer src dest-account amount))))

(transfer-from-all 
  [(accounts 0) (accounts 1) (accounts 2)] 
  (accounts 3) 
  5)

(map deref accounts)
=> (0 0 15 45)

Обратите внимание, что все множественные переносы происходили в одной объединенной транзакции, то есть было возможно «составить» меньшие транзакции.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.