Domanda

E 'sicuro utilizzare la parola 'sincronizzato' sui metodi in un DAO Java andando a causare problemi quando viene utilizzato da un'applicazione web?

Lo chiedo perché ho una sola applicazione multi-threaded stand che ha bisogno di metodi per dal sincronizzato per evitare conflitti di risorse, come si vede qui.

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

Quello che mi preoccupa è che quando un numero significativo di persone si provi ad usare l'applicazione che i metodi sincronizzati saranno bloccare e rallentare l'intera applicazione verso il basso.

Sto usando una molla iniettato JPA fabbrica entità responsabile, che fornisce un gestore di entità al DAO. Potrei tecnicamente rimuovere lo strato DAO e hanno le classi di chiamare direttamente la fabbrica entità direttore, ma mi piace la separazione DAO fornisce.

Vorrei anche sottolineare che io sia molto attento a non passare entità intorno collegato oggetti ORM tra i thread. I speculare che l'errore conflitto di risorse avviene quando si accede al DAO. Credo che più thread stanno andando allo stesso tempo e cercare di persistere o leggere dal database in modi non-atomiche.

In questo caso si utilizza un DAO intenzione di fare più male poi aiutare?


Un grosso pezzo di informazione ho lasciato fuori discussione è che il DAO non è un Singleton. Se avessi pensato abbastanza lucidamente di includere tale dettaglio che probabilmente non avrei fatto la domanda in primo luogo.

Se ho capito bene, Primavera crea una nuova istanza della classe DAO per ogni classe che lo utilizza. Così il sostegno gestore di entità deve essere univoco per ogni thread. Non condivide l'entity manager è, come Rob H rispose, la cosa fondamentale qui.

Tuttavia, ora non capisco il motivo per cui si verificano errori quando rimuovo sincronizzato.


In base a questo infilare , l'annotazione @PersistenceContext crea una filettatura SharedEntityManager sicura. Così si dovrebbe essere in grado di creare un DAO Singleton.

È stato utile?

Soluzione

Lei dice che non si condivide oggetti entità attraverso i thread. Quello è buono. Ma si dovrebbe anche assicurarsi che non stai condividendo EntityManager oggetti (o Sessione oggetti Hibernate) attraverso discussioni sia. Framework come Spring gestire questo per voi automaticamente memorizzando la sessione in una variabile thread-locale. Se stai codifica i propri DAO senza l'aiuto di un quadro, è necessario prendere precauzioni se stessi per evitare la loro condivisione.

Una volta fatto questo, non ci dovrebbe essere alcun motivo per sincronizzare i metodi DAO perché nessuno di Stato conversazione sarà condiviso attraverso i thread. Questo è fondamentale per un'applicazione web altamente concorrente. L'alternativa è che solo un thread potrà accedere DAO in una sola volta, supponendo che tutti condividono la stessa istanza DAO. Non va bene a tutti per il throughput.

Altri suggerimenti

Se deve essere sincronizzato per la sicurezza del filo, poi lasciarli lì. Il blocco è tenuto comunque in quel caso. Se il blocco non è necessario per il caso di applicazioni web, è possibile:

  • lasciarlo così com'è, in quanto le prestazioni colpire quando non c'è conflitto su il blocco è trascurabile, e insignificanti se presi in considerazione la spesa di colpire il database.
  • riprogettare in modo che si aggiunge una strato sincronizzazione per la caso applicativo autonomo che protegge il sottostante DAO non sincronizzato.

Personalmente, vorrei lasciare così com'è e il profilo per vedere se avete bisogno di refactoring. Fino ad allora si sono semplicemente facendo ottimizzazione prematura.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top