problème de concurrence et de verouillage en Java [NEW QUESTION] - Java - Programmation
Marsh Posté le 20-11-2003 à 15:04:20
en lisant rapidement, je m'aperçoit que tu ne créé aucun thread ... donc forcément, ton prg est séquantiel :
remlpace :
Code :
|
par
Code :
|
Marsh Posté le 20-11-2003 à 15:04:55
benou a écrit : en lisant rapidement, je m'aperçoit que tu ne créé aucun thread ... donc forcément, ton prg est séquantiel :
|
.start() benou, .start() !
Edit :
Marsh Posté le 20-11-2003 à 15:06:04
lorill a écrit : .start() benou, .start() ! |
t'aurais du me quoter
Marsh Posté le 20-11-2003 à 15:19:08
Si j'ai bien compris, tu pourrais essayer de mettre cela en evidence, en violant une condition de causalité. Admettons que tu veuilles que la transaction soit uniquement possible si cette operation laisse les 2 comptes positifs (je sais que les banques autorisent les decouverts mais bon ).
Reprenons ta fonction transaction et modifions la
public void passerTransaction(Client c1, Client c2, Banque b1, Banque b2, double somme) {
rajout du test : if (c1-somme>0){
b1.debiterClient(c1, somme);
b2.crediterClient(c2, somme);
System.out.println("Transaction effectuee sur le client " + c1.getNom() + " par la processus " + numero);
}
else
{
System.out.println("transaction impossible" ) ;
}
}
Notons T1 et T2 2 transactions, si elles sont successives, il n'y aura pas de problemes puisque la condition de test sera toujours efficace. Si maintenant ces 2 transactions ont lieu en meme temps (ou quasiment) et que les 2 threads sont tels que :
T1 a reussi le test et s'apprete a executer le code
T2 a finie et est en train d'actualiser le compte en banque.
Alors quand T1 va executer la transaction, la clause de positivité du résultat ne sera plus valide, puisqu'entre temps T2 aura diminuer le compte (par exemple). Tu pourrais donc te retrouver avec un compte negatif, alors que tu avais bien specifie dans ton code le contraire...
Voila j'espere que ca as pu t'aider
Marsh Posté le 20-11-2003 à 16:03:33
C'est un peu cela...
En fait, je voudrais démontrer que si je ne verrouille (de façon exclusive) pas le compte en banque. Je risque d'avoir des incohérences à la fin du programme.
Ex :
P1 P2
LIT(X)
X+1000
LIT(X)
X+2000
ECRIT(X)
ECRIT(X)
D'ou X = X+2000 et non X+3000
Pourriez-vous m'aider à modifier mon code pour me permettre de souligner ce problème de concurrence ?
Merci d'avance !
Marsh Posté le 20-11-2003 à 16:19:31
UPDATE DU CODE :
Classe principale :
Code :
|
classe agent :
Code :
|
Je n'ai jamais d'incohérence alors que je ne gère pas de verrou sur le compte en banque. Peut-être que cela est dû au fait que passerTransaction soit effectué de manière atomique ?
Je rappelle que je veux justement récupérer une erreur pour prouver qu'il faut poser un verrou.
Marsh Posté le 20-11-2003 à 16:20:25
Pour le mettre en évidence, il faut que tu affiches la valeur du compte au milieu de la transaction. Mais il y a un problème dans ton code : tu te protèges déjà en partie contre les accès concurrents, en utilsiant la classe Vector.
Alors, règle importante : oublie la classe Vector en Java, c'est un reste de la première version du langage. Utilise des objets de type List à la place, et initialise-les par un "new ArrayList()". En termes d'implémentation, il n'y a pas de différence, sauf que Vector se protège contre les accès concurrents et ArrayList non.
Ensuite, si tu veux avoir quasiment à coup sûr une erreur dans tes transactions (une fois que tu es sûr de n'utiliser aucune synchronisation inter-thread nulle part, cf. paragraphe précédent), le mieux est sans doute de fixer un "point de rendez-vous" entre 2 threads au milieu de transaction, par un couple wait()/notify().
Marsh Posté le 20-11-2003 à 16:22:19
en même temps, je vais virer vector et considérer kon a 1 seul client dans 1 seul banque, c con mais plus rapide !
Marsh Posté le 20-11-2003 à 16:26:46
Tjrs po d'erreur !
Je désespère.
Qu'entends-tu par : "il faut que tu affiches la valeur du compte au milieu de la transaction " ?
Le résultat devrait de toute manière se voir à la fin.
Marsh Posté le 20-11-2003 à 16:38:30
Roco a écrit : Tjrs po d'erreur ! |
Je pense qu'il voulais dire de pousser les threads à la faute en leur ordonnant d'effectuer leur operation en meme temps :
T1 T2
X+1000 Wait
Wait Wait point de rendez-vous : quand T1 stop -> relance T2
Wair repart : effectue X+2000
Wait Wait
repart Wait
Affiche X+2000
Marsh Posté le 21-11-2003 à 11:33:51
La transaction c'est d'abord un crédit, puis un débit, sur le même compte. On définit une règle de base qui dit qu'un compte ne peut pas avoir une balance négative, règle qu'on vérifie avant chaque transaction. Si tu ne te protèges pas contre les accès concurrents (concurrents dit forcément plusieurs comptes gérés en même temps) et que tu affiches la balance du compte après débit et avant crédit, tu peux te retrouver avec une balance négative malgré le test avant débit qui vérifiait que le débit pouvait se faire sans que le compte passe en négatif.
Tout simeplement parce qu'une autre transaction est venue manipuler le compte au beau milieu de la transaction en cours.
Marsh Posté le 21-11-2003 à 17:22:06
Ben tu fais un println() entre les 2 !
Code :
|
Marsh Posté le 21-11-2003 à 17:24:18
BifaceMcLeOD a écrit : (...) Si tu ne te protèges pas contre les accès concurrents (concurrents dit forcément plusieurs comptes gérés en même temps) (...) |
Je rappelle qu'il te faut forcément plusieurs transactions sur les mêmes comptes en même temps pour mettre en évidence les erreurs dues à l'absence de synchronisation. Et plus il y en aura en même temps, plus tu as de chances de rencontrer une erreur.
Marsh Posté le 20-11-2003 à 15:00:03
Le but de ma démarche est de démontrer que si je ne verouille pas certains objets et que ceux-ci sont lu et modifié par différents processus, au bout, d'un certain temps, ces objets deviendront corrompus.
Mon exemple est celui d'un système bancaire avec un agent qui passe des transactions dans différentes banques sur différents comptes clients. Il fait des virement (débit + crédit).
Problème n°1 (technique) : je n'arrive pas à lancer les processus en parallèles. Malgré l'insertion de sleep et de yeild dans les threads, ceux-ci se déroulent séquentiellement...
Problème n°2 (conception): Je ne pense pas que ma modélisation soit correcte pour démontrer mon objectif. Et je crois que je devrais gérer cela un niveau plus bas (un objet en-dessous).
Voici la classe principale :
Voici la classe Agent :
Voici la classe Banque :
Voici la classe Client :
Et enfin, voici la classe Compte :
Mon but final est d'appliquer des verrous exlusifs sur le comptes et des verrous partagés sur les banques.
Mais d'abord, je voudrais voir l'erreur tourner, sinon je ne pourrais jamais prendre réellement conscience du problème.
Merci d'avance
Message édité par Roco le 20-11-2003 à 16:04:14