Clojure de la STM (dosync) x Java synchroniser bloc


Quelle est la différence entre l'approche Clojure STM (dosync) et le bloc de synchronisation Java?

Je lis le code ci-dessous du problème "The sleeping barber". (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))))

Pour éviter les conditions de concurrence, dosync est utilisé, donc je me demande "Quelle est la différence (STM) de Java synchronize block" ? Va-t-il bloquer ce code critique ?

Merci d'avance ! Dantas

Author: M. Prokhorov, 2010-08-27

4 answers

dosync et synchronized donnent accès à des abstractions de concurrence complètement différentes.

synchronized est un moyen d'acquérir et de suppression des verrous. Lorsqu'un thread entre dans une synchronized bloc, il tente d'acquérir le verrou approprié; si le verrou est actuellement détenu par un autre thread, le thread actuel se bloque et attend d'être libéré. Cela conduit à certains problèmes, tels que le risque de blocage. Le verrou est relâché lorsque le thread quitte le bloc synchronized.

dosync marque un bloc de code qui doit être exécuté dans une transaction. Les transactions dans Clojure sont un moyen de coordonner les modifications apportées aux Refs (objets créés avec la fonction ref); si vous avez besoin de code pour avoir une vue cohérente de certains éléments d'état mutable dans Clojure-et éventuellement les changer-vous les mettez dans Refs et exécutez votre code dans une transaction.

Une transaction a la propriété intéressante qu'elle redémarrera si, pour une raison quelconque, elle ne peut pas valider, jusqu'à un certain nombre maximal de tentatives (actuellement codé en dur pour être 10000). Parmi les raisons possibles pour lesquelles une transaction ne peut pas être validée, il y a l'incapacité d'obtenir une vision cohérente du monde (en fait, les références pertinentes there il y a une facilité "d'historique adaptatif" qui rend cela moins problématique qu'il n'y paraît à première vue); les modifications simultanées apportées par d'autres transactions; etc.

Une transaction ne court aucun risque d'être bloquée (à moins que le programmeur ne fasse tout son possible pour introduire une impasse sans rapport au système STM via Java interop); livelock, d'autre part, est une certaine possibilité, bien que ce ne soit pas très probable. En général, beaucoup, mais pas tous! -- des intuitions que les programmeurs associent aux transactions de base de données sont valables dans le cadre des systèmes STM, y compris celui de Clojure.

STM est un sujet énorme; une excellente ressource pour en apprendre davantage sur la STM de Clojure est l'article de Mark VolkmannSoftware Transactional Memory . Il va en profondeur dans discuter de la STM de Clojure dans ses sections finales, mais le début peut servir de grande lecture introductive.

Quant à l'extrait que vous avez cité, ce n'est en fait pas quelque chose que vous voudriez normalement émuler dans le code de production, car les blocs dosync devraient presque toujours être sans effet secondaire; le print ici peut être utile pour démontrer le fonctionnement interne de la STM, mais si vous vouliez qu'une transaction provoque des effets secondaires (qui n'exécutera sa tâche que si la transaction est validée avec succès).

 19
Author: Michał Marczyk, 2010-08-27 11:47:44

En plus de l'excellente réponse de Michał, avec les transactions STM, lit vous obtenez toujours la valeur gelée au début de la transaction et n'a pas besoin d'attendre la fin de toute transaction en cours.

 3
Author: , 2010-08-27 13:39:14

Juste pour donner une image complète pour ceux qui cherchent, Clojure a un synchronized analogique. C'est utile quand on doit travailler avec des types Java non threadsafe pour interop.

(locking x & body)
 3
Author: jartur, 2010-11-03 00:29:05

La différence de base est la suivante

Clojure STM prend en charge la concurrenceoptimiste alors que JAVA synchronized est pessimiste

Clojure STM n'acquiert pas de verrou tant qu'il n'y a pas plus d'un thread. si l'état mutable est mis à jour par un autre thread, l'opération dans dosync est répétée. En outre, dosync est obligatoire pour les états mutables. Clojure lève l'exception illegalState lorsque dosync est manquant, contrairement à JAVA.

 0
Author: Amrish Pandey, 2016-04-10 16:21:11