2009-03-20 5 views
4

Dans mon application, j'ai une carte de valeur-clé qui sert de référentiel central pour stocker des données qui sont utilisées pour revenir à un état défini après un plantage ou un redémarrage (point de contrôle).Comment puis-je effectuer un instantané thread-safe d'une carte de valeur-clé dans Java?

L'application est multithread et plusieurs threads peuvent mettre des paires clé-valeur dans cette carte. Un thread est responsable de la création régulière d'un point de contrôle, i. e. sérialiser la carte pour un stockage persistant. Pendant que le point de contrôle est en cours d'écriture, la carte doit rester inchangée. Il est plutôt facile d'éviter l'ajout de nouveaux éléments, mais qu'en est-il des autres threads qui changent les membres de "leurs" objets à l'intérieur de la map?

Je pourrais avoir un seul objet dont le moniteur est saisi lorsque le point de reprise commence et envelopper tous les accès en écriture à n'importe quel membre de la carte, et à ses membres, dans la synchronisation des blocs sur cet objet. Cela semble très sujet à erreur et fastidieux pour moi.

Je pourrais aussi rendre la carte privée au checkpointer et ne placer que des copies des objets soumis. Mais alors je devrais m'assurer que les copies sont des copies profondes et je ne serais pas capable d'avoir les données dans la carte étant automatiquement mises à jour, à chaque changement aux objets soumis, les soumissionnaires devraient les soumettre de nouveau. Cela semble beaucoup de frais généraux et aussi sujettes aux erreurs, car je dois me rappeler de remettre le code dans tous les bons endroits.

Qu'est-ce qu'un moyen élégant et fiable de résoudre ce problème?

Répondre

1

pgras a raison de dire que l'immuabilité pourrait arranger les choses, mais ce serait aussi difficile. Vous pourriez juste verrouiller le tout mais cela pourrait être un problème de performance. Je peux penser à deux bonnes idées.

La première consiste à utiliser un ReadWriteLock (qui requiert la version 1.5 ou ultérieure). Depuis que votre point de contrôle peut acquérir le verrou de lecture, il peut être assuré que les choses sont en sécurité, mais quand personne ne lit la performance devrait être assez bonne. C'est encore un joli verrou grossier, donc vous pouvez également vouloir # 2 ...

Deuxièmement est de casser les choses. Chaque zone du programme peut conserver sa propre carte (la carte pour les éléments graphiques, la carte pour les paramètres utilisateur, la carte pour les paramètres matériels, etc.). Chacun aurait un verrou dessus et les choses iraient comme d'habitude. Quand il est temps de checkpoint, le checkpointer saisit tous les verrous (donc les choses sont cohérentes) et ensuite faire son travail. La capture ici est que vous avez définir un ordre pour les serrures à saisir (disons alphabétique) sinon vous finirez avec des blocages. Si les cartes sont orthogonales entre elles (les mises à jour de l'une ne nécessitent pas de mises à jour d'une autre), la solution la plus simple consiste à pousser les mises à jour vers une carte de sauvegarde centrale dans le checkpointer. quelque chose que tu as décrit.

Ma plus grande question à vous serait, quel est le problème (performance sage)? Les mises à jour sont-elles très fréquentes ou sont-elles rares? Cela aiderait à donner des conseils sur quelque chose puisque ma dernière idée (paragraphe précédent) pourrait être lente, mais c'est facile et peut ne pas importer.

Il existe un livre fantastique appelé Java Concurrency in Practice qui est fondamentalement la bible Java. Il discute de la façon de comprendre ce genre de choses et de stratégies pour éviter les problèmes ou pour les résoudre plus facilement. Si vous allez faire plus de threads, c'est une lecture très utile.

En fait, si vos valeurs de clé sont orthogonales les unes aux autres, alors les choses sont vraiment faciles. L'interface ConcurrentMap (il y a implemetations telles que ConcurrentHashMap) résoudrait vos problèmes puisqu'ils peuvent faire des changements atomiquement, donc les lecteurs ne verront pas de données incohérentes. Mais si vous avez deux clés (ou plus) qui doivent être mises à jour en même temps, cela ne vous couvrira pas.

J'espère que cela aide. L'accès par threading à des structures de données partagées est complexe.

2

ce que d'autres sujets changeants membres de « leurs » objets à l'intérieur de la carte

Ici vous avez un problème :) et il ne peut pas être résolu par tout type de carte ...

Une solution serait de ne permettre que des objets immuables dans votre carte, mais cela peut être impossible pour vous. Dans le cas contraire, vous devez partager un verrou pour tous les threads susceptibles de modifier les données référencées par votre map et de les bloquer pendant l'instantané; mais c'est une approche de stop the world ...

+0

+1 objets immuables, la carte est un instantané de l'état. Travaillez votre clone/serialization et rappelez-vous de lire sur le mot-clé transitoire – basszero

Questions connexes