dosync
и synchronized
предоставляют доступ к совершенно различным абстракциям параллелизма.
synchronized
- способ приобретения и освобождения замков. Когда поток входит в блок synchronized
, он пытается получить соответствующую блокировку; если блокировка в настоящее время поддерживается другим потоком, текущий поток блокирует и ждет его освобождения. Это приводит к определенным проблемам, таким как риск тупика. Блокировка отпускается, когда нить покидает блок synchronized
.
dosync
отмечает блок кода, который должен быть запущен в транзакции. Транзакции в Clojure - это способ координации изменений в Ref (объекты, созданные с помощью функции ref
); если вам нужен какой-то код для последовательного просмотра некоторых частей изменчивого состояния в Clojure - и, возможно, их изменение, вы помещаете их в Refs и выполняете свой код в транзакции.
Сделка имеет интересное свойство, что она будет перезагружаться, если по какой-либо причине она не может совершить, до определенного максимального количества попыток (в настоящее время жестко запрограммировано на 10000). Среди возможных причин невозможности совершения транзакции - невозможность получить последовательное представление о мире (на самом деле, соответствующие Refs - существует объект «адаптивной истории», который делает это менее проблематичным, чем может показаться на Первый взгляд); одновременные изменения, сделанные другими транзакциями; и т. д.
Сделка не подвергается риску оказаться в тупике (если программист не собирается вводить тупик, не связанный с системой STM через Java-взаимодействие); livelock, с другой стороны, является определенной возможностью, хотя это не очень вероятно. В общем, многие - хотя и не все! - интуитивных программистов, связанных с транзакциями базы данных, действительны в контексте STM-систем, в том числе Clojure.
STM - это огромная тема; одним из превосходных ресурсов для изучения STM компании Clojure является статья Марка 0 Software Transactional Memory Марка Volkmann. Он углубляется в обсуждение STM Clojure в своих заключительных разделах, но начало может послужить отличным вводным чтением.
Что касается фрагмента, который вы цитировали, на самом деле это не то, что вы обычно хотели бы эмулировать в производственном коде, поскольку блоки dosync
должны почти всегда быть свободными от побочных эффектов; print
здесь могут быть полезны для демонстрации внутренней работы STM, но если вы хотите, чтобы транзакция вызывала побочные эффекты в реальном коде, вам нужно, чтобы она создала агента Clojure для этой цели (которая выполнила бы только свою задачу, если транзакция успешно совершает).
Добро пожаловать. :-) –
Привет, Михль, как и я ответил мне о STM отлично, позвольте мне спросить еще кое-что о clojure, что я не понимаю. Форма коммутирования. Предположим, что у меня есть 2 потока (t1 и t2). И идеология увеличивает ссылку, хорошо? t1 внутри dosync, получить значение ref - в транзакционном значении (0) - ... t2 получить контроль и смог увеличить значение от 0 до 1. t1 вернется и что он должен делать? wether t1 продолжает выполнение конечного результата не будет правильным. как коммутируют в этом случае? заранее спасибо – CHAPa