Clojure STM ( dosync ) x Java synchronize block

What is the difference between Clojure STM (dosync) approach and Java synchronize Block?

I'm reading the code below from "The sleeping barber" problem. (http://www.bestinclass.dk/index.clj/2009/09/scala-vs-clojure-round-2-concurrency.html)

(defn the-shop [a]  
  (print "[k] entering shop" a)  
  (dosync     
    (if (< (count @queue) seats)  
      (alter queue conj a)  
      (print "[s] turning away customer" a))))

To avoid race conditions, dosync is used, so i ask myself "What is the difference (STM) from Java synchronize block" ? Will it block this critical code ?

Thanks in advance ! Dantas

11
задан M. Prokhorov 30 March 2018 в 10:59
поделиться

2 ответа

dosync и synchronized предоставляют доступ к совершенно разным абстракциям параллелизма.

synchronized — это способ получения и снятия блокировок. Когда поток входит в блок synchronized, он пытается получить соответствующую блокировку; если блокировка в настоящее время удерживается другим потоком, текущий поток блокируется и ожидает ее освобождения. Это приводит к определенным проблемам, таким как риск взаимоблокировки. Блокировка снимается, когда поток покидает блок synchronized.

dosync отмечает блок кода, который должен выполняться в транзакции. Транзакции в Clojure — это способ координации изменений в Refs (объекты, созданные с помощью функции ref); если вам нужен некоторый код, чтобы иметь согласованное представление некоторых частей изменяемого состояния в Clojure — и, возможно, изменить их — вы помещаете их в ссылки и выполняете свой код в транзакции.

Транзакция имеет интересное свойство: она будет перезапущена, если по какой-то причине не может быть зафиксирована, вплоть до определенного максимального количества повторных попыток (в настоящее время жестко задано значение 10000). Среди возможных причин того, что транзакция не может быть зафиксирована, — невозможность получить непротиворечивое представление о мире (на самом деле, соответствующие ссылки — есть функция «адаптивной истории», которая делает эту проблему менее серьезной, чем может показаться на первый взгляд). Первый взгляд); одновременные изменения, сделанные другими транзакциями; и Т. Д.

Транзакция не рискует зайти в тупик (если только программист не приложит все усилия, чтобы ввести взаимоблокировку, не связанную с системой STM, посредством взаимодействия Java); livelock, с другой стороны, является определенной возможностью, хотя и маловероятной. В общем, многие -- хотя и не все! -- интуиции, которые программисты связывают с транзакциями баз данных, действительны в контексте систем STM, включая Clojure.

STM — обширная тема; Одним из замечательных источников информации о STM в Clojure является статья Марка Фолькманна Software Transactional Memory. В заключительных разделах мы подробно обсуждаем Clojure STM, но начало может послужить отличным вводным чтением.

Что касается процитированного вами фрагмента, на самом деле это не то, что вы обычно хотели бы эмулировать в производственном коде, поскольку блоки dosync почти всегда должны быть свободны от побочных эффектов; print здесь может быть полезен для демонстрации внутренней работы STM, но если вы хотите, чтобы транзакция вызывала побочные эффекты в реальном коде, вы должны создать агента Clojure для этой цели (что выполнять свою задачу только в том случае, если транзакция успешно зафиксирована).

20
ответ дан 3 December 2019 в 03:51
поделиться

Кроме того, в дополнение к отличному ответу Михала, с транзакциями STM чтения всегда дают вам замороженное значение в начале транзакции, и вам не нужно ждать, пока какая-либо текущая транзакция завершится. полный.

3
ответ дан 3 December 2019 в 03:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: