IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

[Synchronized] Strategie de synchronisation pour une classe de CRUD


Sujet :

Java

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2006
    Messages : 122
    Par défaut [Synchronized] Strategie de synchronisation pour une classe de CRUD
    Salut,

    Je viens de finir une classe implementant un CRUD, et je me pose des questions sur la solidite de ma strategie de synchronisation. Je me rends compte que je vais certainement avoir des problemes de performance (parfois voulus car je dois garder le code le plus simple possible, mais souvent subis), mais je veux avant tout m'assurer que la BDD ne pourra pas etre corrompue, a aucun moment par aucun thread. Voyez vou une erreur dans ce design ?

    NB : Delete une entree signifie juste set un flag sur cette entree. Pour creer une nouvelle entree, on ecrase une entree deleted s'il y en a au moins une, sinon on ecrit a la fin de la BDD. Je garde en memoire la liste des id des entrees deleted (deletedRecordCache) ainsi que le nombre total d'entrees (nbTotalRecord) (et c'est la que ca pourrait se gater)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    method read(int idEntree) :
    1- verifier que deletedRecordCache ne contient pas idEntree (exit si c'est le cas)
    2- Atomic : se placer au bon endroit et lire l'entree
    3- verifier sur l'entree elle meme qu'elle n'est pas deleted
    4- retourner l'entree
    Toutes les autres methodes se reposent sur read(). Toutes l'appellent directement ou indirectement pour savoir si l'entree existe. Une entree existe si et seulement si
    - son id est compris entre 0 et (nbTotalRecord -1)
    - elle n'est pas deleted
    Si ce n'est pas le cas, une exception est levee.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    method create() :
    1- Atomic : a- se placer a la position de la 1ere entree dans deletedRecordCache ou a la fin de la BDD
    b- ecrire l'entree
    c- mettre a jour le nombre total d'entrees si ecriture a la fin de la BDD
    d- mettre a jour deletedRecordCache
    2- retourner l'id de l'entree cree
    
    method update(int idEntree) :
    1- Atomic : a- appeler indirectement read() pour voir si l'entree existe
       b- se placer au bon endroit et ecrire l'entree
    
    method delete(int idEntree) :
    1- Atomic : a- appeler indirectement read() pour voir si l'entree existe
       b- se placer au bon endroit et set le deleted flag
    
    A cela s'ajoute une methode find, dont je ne suis pas fiere, mais j'ai un peu de mal a trouver une alternative acceptable.
    
    method find(String criterium) : 
    1- Atomic : a- lire (avec read() )les entrees directement dans la BDD, une par une, et a chaque fois, si read() a reussi (ie l'entree n'est pas deleted), comparer l'entree avec le critere. 
    2- retourner la liste des id qui correspondent au critere.
    Autocritique : Lorsque j'ecris Atomic, comprenez que je fais un synchronized(dbAccessObject). Je comprends de cette syntaxe qu'aucun thread ne peut acceder a dbAccessObject, et que je peux donc modifier la BDD sans risque de la corrompre. Est ce correct ? D'apres la doc, on peut synchroniser sur n'importe quoi, et cela empecherait juste les autres thread de penetrer la zone critique. Comment faire pour etre sur qu'aucune mehode/thread n'essaiera de lire/ecrire dans la BDD lorsqu'un autre essaie de la modifiee ?

    Toutes les methodes citees plus haut ont la plupart de leur code contenu dans un synchronized block. Ce qui me gene, c'est que pour peu que la BDD soit utilisee intensivement, avec un read(), delete() et update() qui arrivent en meme temps, la derniere methode mettra beaucoup de temps a revenir. Mais j'ai du mal a voir comment m'arranger pour que mes methodes ne soient pas de gros blocs synchronized sans finesse, et que je me retrouve avec une queue de requetes s'empilant les une sur les autres en attendant que la precedante est quittee la BDD. Quelles sont vos astuces/conseils/critiques au regard du process ci-dessus, tout en gardant la BDD coherante (ce qui je pense est le cas, au prix des perfs, mais si vous voyez un cas qui corrompt la BDD, n'hesitez pas)

    find() est pire : j'ai decide de lire directement les entrees dans la BDD, une a une (tres lent), au lieu de mettre en cache toutes les entrees, liberer la BDD pour que d'autres puissent y faire des operations (create, read...), et pendant ce temps, verifier mes criteres sur mon cache. Mon idee est que si je cache les donnees, la methode sera plus rapide mais les donnes auront plus de chance d'etre corrompues au moment ou je renvoie les resultats de la recherche (retourner un resultat qui a ete detruit juste apres la creation du cache par exemple). Alors que si je bloque l'access, j'ai plus de chance de retourner un resultat correct. Mais dans les 2 cas, je sais qu'il n'y a aucune garantie que le resultat retourne sera conforme a l'etat actuel de la BDD. Pensez-vous que j'ai raison d'abandonner les perfs a une plus(?) grande chance de coherance ?

    Pour etre complet, ceci est un exercice qui fait partie de la SCJD. Faites moi savoir - gentillement - si j'en demande trop.

    Nuriel

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    bon alors j'aurais tendance, avis personnel, a dire t'emmerde pas, utilise des transations JDBC que tu met en isolation "SERIALIZABLE" et c'est la base de données qui va te protéger de la corruption. De plus même si tu n'utilise pas d'isolation, je suis surpris que tu ne mentionne pas les positions des transaction dans ton message, c'est pourtant quelque chose de critique.

    Exemple pour l'isolation:

    --début de transaction
    begin()
    Lire certaines lignes
    modifier des valeurs pour certaines
    Ecrire de nouvelles lignes
    commit()
    --- fin de transaction

    Si entre le begin et le commit
    -> le lignes lues ont été modifiée par un autre thread
    -> ou les ids utilisés ont été utilisés par un autre thread (sous reserve de contrainte d'unicité)
    -> ou ... (certaines opérations sql qui pourraient entrer en conflit)
    alors lors de ton commit ta base de donner va t'envoyer une exception et tu saura que l'opération est inutile / impossible.

    Toutes les methodes citees plus haut ont la plupart de leur code contenu dans un synchronized block. Ce qui me gene, c'est que pour peu que la BDD soit utilisee intensivement, avec un read(), delete() et update() qui arrivent en meme temps, la derniere methode mettra beaucoup de temps a revenir. Mais j'ai du mal a voir comment m'arranger pour que mes methodes ne soient pas de gros blocs synchronized sans finesse, et que je me retrouve avec une queue de requetes s'empilant les une sur les autres en attendant que la precedante est quittee la BDD. Quelles sont vos astuces/conseils/critiques au regard du process ci-dessus, tout en gardant la BDD coherante (ce qui je pense est le cas, au prix des perfs, mais si vous voyez un cas qui corrompt la BDD, n'hesitez pas)
    comme dit plus haut, transaction et isolation -> ca laisse tout le loisir à la DB d'utiliser ses algos performants pour réduire les goulots et te permet de réduire au minimum tes propres goulots.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    122
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2006
    Messages : 122
    Par défaut
    Merci. Je n'ai pas donne une precision importante : la BDD est un bete fichier d'octets. Connaissant la taille d'un enregistrement et la position du premier, je sais me deplacer dans ce fichier pour retrouver la position (ce que j'appelle idEntree) de n'importe quelle entree. Je ne peux donc pas me reposer - pour l'instant - sur un systeme qui gererait les transactions pour moi. L' esprit du texte est justement que je me casse la tete pour en creer un, et je cherche des avis pour voir si ma solution tient la route ou si je me suis royalement plante.

    J'espere en etre a l'acces a une vraie BDD fin de semaine prochaine. Je garde donc ton message sous le coude.

    ++

    Nuriel

Discussions similaires

  1. Définition de méthodes pour une classe template
    Par Pragmateek dans le forum Langage
    Réponses: 13
    Dernier message: 20/12/2008, 00h46
  2. Affichage bizarre pour une classe lettre
    Par Aline2611 dans le forum Mise en forme
    Réponses: 2
    Dernier message: 07/08/2006, 09h27
  3. Héritage d'un événement pour une classe fille
    Par korntex5 dans le forum Langage
    Réponses: 4
    Dernier message: 11/01/2006, 16h48
  4. Réponses: 8
    Dernier message: 02/11/2005, 20h21
  5. ecrire un iterateur pour une classe
    Par Blowih dans le forum C++
    Réponses: 2
    Dernier message: 15/11/2004, 19h19

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo