2010-11-14 6 views
1

Comment fonctionne vraiment le travail. (trajet IDENTITÉ FONCTION & valeurs)Comment fonctionne le transport?

la Documentation Clojure dit:

Utilisation: (trajet ref plaisir & args)

doit être appelé dans une transaction. (Définit la valeur transactionnelle de ref à:

(applique des arguments amusants dans la transaction-value-of-ref) et retourne la valeur de transaction de ref.

Au point d'engagement de la transaction, définit la valeur de ref être:

(appliquer le plaisir le plus récemment commis-valeur de-ref args)

Ainsi, le formulaire de trajet est effectuée en deux phases.

est la deuxième phase atomique (appliquer le plaisir le plus récemment commis-valeur de-ref args)

sinon, ce qui se passe dans cet exemple: 2 fils (T1 et T2).

Les deux vont incrémenter (fonction commutative) la même identité.

IDENTITY: (def i (ref 0) 
     (dosync (commute inc i)) 

T1 dans la première étape de l'inc d'appel de trajet avec ref i = 0 (en valeur transactionnelle = 1)

T1 arrêt

T2 dans la première étape de l'appel de trajet inc avec ref i = 0 (en valeur transactionnelle = 1)

T2 arrêt

T1 dans la deuxième étape appel inc nouveau avec la dernière valeur engager i = 0, le retour de la fonction inc, mais avant u pdate l'arbitre (i) T1 arrêt

T2 dans le deuxième appel de l'étape inc nouveau avec la dernière valeur engager i = 0 et mettre à jour la référence

T1 recommencer et mettre à jour la référence à la inc valeur renvoyée = 1

Ceci est un problème de condition de concurrence? comment clojure éviter cela? si la deuxième phase est atomique, cela n'arrivera pas.

Merci à l'avance

MISE À JOUR: si je comprends bien la dernière phase des opérations de déplacement (point d'engagement) est synchronisé « fun UNLOCK ** LOCK trajet »?

Répondre

5

La clé est de réaliser que la valeur en transaction de la ref (résultant d'un trajet) peut en fait être différente de la valeur qui est finalement écrite à l'arbitre au point de validation.

Dans votre exemple, les threads T1 et T2 exécutent leurs transactions simultanément, avec i se référant à 0. Les deux (inc i) via commutent, et donc tous les deux voient i = 1 lors de leurs transactions.Lorsqu'ils sont prêts à être validés, la fonction spécifiée dans le trajet (inc) sera appliquée à la référence en utilisant la valeur la plus récemment validée. Donc, si T1 commet en premier, i = 1, alors T2 commet, et i = 2. En réponse à votre question, ces commits sont en effet atomiques, et donc aucune condition de course n'est possible.

je cite la documentation de trajet ci-dessous:

Au point d'engagement de la transaction, définit la valeur de ref être:

(apply fun most-recently-committed-value-of-ref args)

Ainsi le plaisir devrait être commutative, ou, à défaut, vous devez accepter le comportement du dernier en un.

Le « dernier-one-in-victoires » bit vous avertit que si la fonction vous postulez est pas commutative - multiplication matricielle vient à l'esprit - alors en fait une condition de course est possible . C'est-à-dire que la transaction qui valide en premier aura sa fonction appliquée à la valeur ref "originale", et que la prochaine transaction à valider aura sa fonction appliquée à l'état mis à jour. Les applications de fonction sont toujours appliquées atomiquement, cependant.

+1

Nice Michaelle. Donc, si je comprends bien, la dernière phase des opérations de navette (point de validation) est synchronisée "LOCK commute fun UNLOK"? – CHAPa

Questions connexes