11
votes

CLOJURE STM (DOSYNC) X Java Synchronize Block

Quelle est la différence entre l'approche de CLOJURE STM (DOSYNC) et Java Synchronize Block?

Je lis le code ci-dessous de "The Barber Sleep Barber". ( http: // www .Bestinclass.dk / index.clj / 2009/09 / scala-vs-clojure-rond-2-cachrency.html ) xxx

Pour éviter les conditions de course , dosync est utilisé, alors je me demande "quelle est la différence (STM) du bloc de synchronisation Java"? Cela bloquera-t-il ce code critique?

Merci d'avance! Dantas


1 commentaires

Salut, Michl, comme tu m'as répondu à propos de la STM parfaitement, permettez-moi de demander à une autre chose de clojure que je ne réalisons pas. La forme de trajet. Supposons que j'ai 2 threads (T1 et T2). Et l'Idea est incrémentation d'une référence, d'accord? T1 à l'intérieur d'un dosync, obtenez la valeur Ref - en valeur de transaction (0) - ... T2 Obtenez le contrôle et a été capable d'incrémenter la référence de 0 à 1. T1 Reviens, et ce que c'est supposé faire? Wether T1 continue d'exécuter le résultat final ne sera pas correct. Comment les commutes fonctionnent dans ce cas? Merci d'avance


4 Réponses :


20
votes

dosync et synchronisé donner accès à des abstractions simultanées complètement différentes.

synchronisé est un moyen d'acquérir et de libérer des serrures. Lorsqu'un thread entre dans un bloc synchronisé , il tente d'acquérir la serrure appropriée; Si la serrure est actuellement maintenue par un fil différent, le thread de courant bloque et attend qu'il soit libéré. Cela conduit à certains problèmes, tels que le risque d'impasse. La serrure est relâchée lorsque le thread quitte le bloc synchronisé .

DOSYNC marque un bloc de code qui doit être exécuté dans une transaction. Les transactions à Clojure sont un moyen de coordonner les modifications apportées aux REF (objets créés avec la fonction ref ); Si vous avez besoin de code pour avoir une vue cohérente de quelques pièces d'état mutable dans le clojure - et éventuellement les modifier - vous mettez ceux-ci dans les réfs 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 commettre, jusqu'à un certain nombre maximal de tentatives (actuellement codé dur à 10000). Parmi les raisons possibles d'une transaction incapable de s'engager, c'est une incapacité à obtenir une vision cohérente du monde (en fait, les réfs correspondants - il existe une installation "Histoire adaptative" qui fait cela moins de problème qu'il ne semblerait que au premier coup d'œil); modifications simultanées effectuées par d'autres transactions; c.

Une transaction ne fonctionne aucun risque d'être sans égard (à moins que le programmeur ne se limite à introduire une impasse sans rapport avec le système STM via Java Interop); Livelock, d'autre part, est une certaine possibilité, même si ce n'est pas très probable. En général, beaucoup - mais pas tous! - des programmeurs d'intuition associés aux transactions de base de données sont valables dans le contexte des systèmes STM, y compris celui de Clojure.

STM est un énorme sujet; Une excellente ressource pour apprendre à propos de la STM de Clojure est Mark Volkmann's Mémoire transactionnelle logicielle article. Il va en grande profondeur dans la discussion 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 pas quelque chose que vous voudriez normalement imiter dans le code de production, car Les blocs DOSYNC doivent presque toujours être libres de côté; le impression ici peut être utile pour démontrer le fonctionnement intérieur de la STM, mais si vous vouliez qu'une transaction provoque des effets secondaires en code réel, vous devriez l'avoir généré un agent de clojure à cet effet (qui ne serait exécuté que sa tâche si la transaction s'engage avec succès).


7 commentaires

Michal, vous avez écrit "car les blocs Dosync devraient presque toujours être sans effet secondaire libre". Une impression de console brisera cette propriété "Effet secondaire"? Donc, mettre à jour une table de base de données fera la même chose, d'accord? Qu'est-ce qui est supposé être à l'intérieur d'un bloc dosync? Merci encore, excellent post!


Droite, imprimez sur la console et mettez à jour une table de base de données qualifiée d'effets secondaires. DOSYNC Les blocs sont en général non censés contenir du code secondaire sauf des appels aux fonctions de modification de la transaction ( alter / / Commute / REF-SET ), avec l'exception importante que toutes les actions envoyées aux agents peuvent contenir des effets secondaires destinés à se produire après la fin de la transaction (toutes ces actions seront effectuées si et lorsque la La transaction s'engage, il n'ya donc aucun risque de causer plus de fois le même effet secondaire qu'une fois).


Donc, si vous aviez besoin de modifier les valeurs d'un couple de réfs et de mettre à jour votre base de données, votre dosync contiendrait alter / commute appels pour changer les refs et un envoi / envoi indiquent à un agent d'exécuter la mise à jour de la DB une fois que la transaction s'engage (et ne fonctionne plus le risque de réessayer ou de défaillance en raison de la réessayer la limite d'être atteinte).


Oh, également, sur les impressions "presque" - de débogage dans les transactions peut être aussi utile que n'importe où ailleurs (en particulier, ils vous diront combien de fois votre transaction devait réessayer, car "barbier endormi" de Lau démontre gentiment); Les appels à des fonctions mémotionnés de l'intérieur des transactions devraient bien sûr causer l'effet secondaire de l'enregistrement des valeurs nouvellement calculées; etc. Néanmoins, il faut être vraiment sûr de ce que l'on fait de ce que son faisant lors de l'introduction d'effets secondaires à l'intérieur Dosync - beaucoup de casse peut résulter d'un manque de soins sur ce point.


Merci michał. Excellente vue! Vraiment sympa !


Lorsque vous SEND-OFF Un agent de l'intérieur d'un DOSYNC , il ne fonctionne pas tant que le Dosync se termine. Cela signifie qu'il est trop tard pour annuler la transaction STM si quelque chose ne va pas dans votre agent, qui est toujours possible si votre agent accède à des bases de données (DB pourrait rejeter vos données ou le serveur peut être en panne). Je pense que la coordination d'une référence Ref et une base de données est actuellement très difficile (ou impossible?) Même en utilisant des agents.


Oh, c'est absolument vrai ...! Merci pour le commentaire. Cela va juste confirmer ma suspicion que mon stm-fu est un peu rouillé ...



3
votes

Également en plus de la réponse excellente de Michał, avec des transactions STM, lit vous permettez toujours de la valeur gelée au début de la transaction et ne devez pas attendre que toute transaction en cours soit terminée.


1 commentaires

Oui ! Les opérations de lecture ne nécessitent pas de verrouillage. Il est libre de verrouiller. Quand tu lis, tu reçois un instantané. Mais si vous écrivez, l'opération ne s'engage que si l'instantané est égal de ce que vous avez. Si quand vous essayez d'écrire, les données ne sont pas identiques, le retour d'opération.



3
votes

Juste pour donner une image complète pour ceux qui recherchent, Clojure a un synchronisé analogique. Il est utile quand on doit fonctionner avec des types Java non threadsafe pour Interop. xxx


0 commentaires

0
votes

La différence de base suit

CLOJURE STM prend en charge Concurrence optimiste tandis que Java synchronisé est pessimiste

CLOJURE STM n'accepte pas de verrouillage tant qu'il n'y ait pas plus d'un fil. Si l'état mutable est mis à jour par un autre thread, l'opération à l'intérieur DOSYNC est répétée. En outre, dosync est obligatoire pour les états mutables. Clojure jette une exception illégale de l'installation lorsque Dosync est manquant, contrairement à Java.


1 commentaires

Eh bien, ce sont des types assez différents de soutien de la concurrence (accès transactionnel à des valeurs mutables par rapport à la mise en œuvre de Sections critiques Utiliser synchronisé ) afin qu'ils ne puissent pas vraiment être comparés. Si Java avait STM implémenté avec verrouillage à deux phases puis on pourrait comparer et dire "c'est Un "protocole" optimiste "" (non "Concurrence optimiste", qui sonne comme une partie) et "c'est un" protocole "pessimiste". C'est une chose de DBMS! Et il est même bas de ne pas la STM, mais la mise en œuvre de CLOJURE de CLOJURE.