Я просматриваю книгу 7 concurrency models in 7 weeks
. В нем философы представлены в виде числа ref
:
(def philosophers (into [] (repeatedly 5 #(ref :thinking))))
Состояние каждого философа переключается между :thinking
и :eating
с использованием dosync
транзакций для обеспечения согласованности.
Теперь я хочу иметь поток, который выводит текущий статус, чтобы я мог быть уверен, что состояние действительно всегда:
(defn status-thread []
(Thread.
#(while true
(dosync
(println (map (fn [p] @p) philosophers))
(Thread/sleep 100)))))
Мы используем несколько @
для чтения значений каждого философа. Может случиться так, что некоторые ссылки будут изменены, поскольку мы map
над философами. Не приведет ли это к тому, что мы будем печатать противоречивое состояние, хотя у нас его нет?
Я знаю, что Clojure использует MVCC
для реализации STM
, но я не уверен, что применяю его правильно.
Моя транзакция содержит побочные эффекты, и обычно они не должны появляться внутри транзакции. Но в этом случае транзакция всегда будет успешной, а побочный эффект должен иметь место только один раз. Это приемлемо?