Question

utilise le mot-clé « synchronisée » sur les méthodes dans un DAO Java va causer des problèmes lorsqu'ils sont utilisés par une application web?

Je demande parce que j'ai une application stand alone multi-thread qui a besoin des méthodes par synchronisées pour éviter les conflits de ressources, comme on le voit ici.

java.util.concurrent.ExecutionException: javax.persistence.PersistenceException: org.hibernate.HibernateException: Found shared references to a collection: com.replaced.orm.jpa.Entity.stuffCollection

Ce que je suis préoccupé par est que lorsqu'un nombre important de personnes essayer d'utiliser l'application que les méthodes synchronisées bloquer et ralentir l'ensemble de l'application vers le bas.

J'utilise un ressort Injecté usine de gestionnaire d'entités JPA, qui fournit un gestionnaire d'entités au DAO. Je pourrais techniquement enlever la couche de DAO et ont les classes appellent l'usine de gestionnaire d'entités directement, mais j'aime la séparation du DAO fournit.

Je tiens également à noter que je suis en faisant très attention de ne pas passer l'entité autour des objets connectés ORM entre les fils. Je spécule que l'erreur de conflit de ressources se réalise lors de l'accès au DAO. Je pense que plusieurs threads vont en même temps et essayer de persister ou lire à partir de la base de données de manière non-atomiques.

Dans ce cas, utilise un DAO va faire plus de mal alors aider?


Un gros morceau d'information je suis parti de la question est que le DAO n'est pas un singleton. Si je l'avais pensé assez lucidement pour inclure ce détail je ne serais probablement pas posé la question en premier lieu.

Si je comprends bien, Spring crée une nouvelle instance de la classe DAO pour chaque classe qui l'utilise. Ainsi, le gestionnaire d'entités de soutien doit être unique à chaque fil. Ne partage pas le directeur de l'entité est, comme Rob H répondit la chose clé ici.

Cependant, maintenant je ne comprends pas pourquoi je reçois des erreurs lorsque je retire synchronisation.


Selon cette fil , l'annotation @PersistenceContext crée un thread- SharedEntityManager sûr. Donc, vous devriez être en mesure de créer un DAO singleton.

Était-ce utile?

La solution

Vous dites que vous ne partagez pas les objets d'entité dans les threads. C'est bon. Mais vous devez également vous assurer que vous ne partagez pas EntityManager objets (ou Session objets Hibernate) dans les threads non plus. Cadres comme le printemps gérer automatiquement pour vous en stockant la session dans une variable de thread local. Si vous codez vos propres OTI sans l'aide d'un cadre, vous devez prendre des précautions pour éviter vous les partager.

Une fois que vous faites cela, il devrait y avoir aucune raison de synchroniser les méthodes de DAO, car aucun de l'état de conversation sera partagé entre les threads. Cela est essentiel pour une application Web hautement concurrente. L'alternative est qu'un seul thread pourra accéder au DAO à un moment donné, en supposant qu'ils partagent la même instance de DAO. Pas bon du tout pour le débit.

Autres conseils

S'il doit être synchronisé pour la sécurité des threads, puis les laisser là-bas. Le blocage est nécessaire de toute façon dans ce cas. Si le blocage n'est pas nécessaire dans le cas d'applications Web, vous pouvez:

  • le laisser tel quel, puisque la performance frapper quand il n'y a pas de conflit sur la serrure est négligeable, et insignifiants pris en compte la charge de frapper la base de données.
  • Refonte pour que vous ajoutez un couche de synchronisation pour la cas d'application autonome qui protège le sous-jacent désynchronisé OAC.

Personnellement, je laisse tel quel et le profil pour voir si vous avez besoin de factoriser. Jusque-là, vous faites simplement l'optimisation prématurée.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top