Как на самом деле работает коммутирует.(коммутировать IDENTITY FUNCTION и значения)
Документация Clojure гласит:
Использование: (commute ref fun & args)
Должен вызываться в транзакции.Устанавливает значение in-транзакции ref равным:
(применяет забавные аргументы in -action-value-of-ref) и возвращает значение in-транзакции ref.
Вточка фиксации транзакции устанавливает значение ref следующим образом:
(применяет забавные аргументы "последнее добавленное значение-ref-аргумента")
Таким образом, форма коммутированиявыполняется в два этапа.
является ли второй этап атомарным? (примените забавные аргументы "последнее добавленное значение-из-ref")
, если нет, что произойдет в этом примере: 2 потока(T1 и T2).
Оба будут увеличивать (коммутативная функция) один и тот же идентификатор.
IDENTITY: (def i (ref 0 )
(dosync (commute inc i ) )
T1 на первом шаге вызова на коммутацию inc с ref i = 0 (в транзакциизначение = 1)
остановка T1
T2 на первом шаге коммутируемого вызова inc с ref i = 0 (в значении транзакции = 1)
остановка T2
T1 во втором шаге снова вызывает inc с последним значением коммита i = 0, функция inc возвращается, но перед обновлением ref (i) T1 останавливается
T2 во втором шаге снова вызовите inc с последним значением фиксации i = 0 и обновите ссылку
T1 запустите снова и обновите ссылку с возвращенным значением inc = 1
Это проблема состояния гонки?Как избежать этого?если вторая фаза будет атомарной, этого не произойдет.
Заранее спасибо
ОБНОВЛЕНИЕ: если я правильно понимаю, последняя фаза операций коммутации (точка фиксации) синхронизирована "LOCK commuteвесело разблокировать ** "?