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)
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
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
- 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.
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 ?
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.
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
Partager