Si tengo una clase util con métodos estáticos que llamarán a las funciones de Hibernate para lograr el acceso básico a datos. Me pregunto si hacer el método synchronized
es el enfoque correcto para garantizar la seguridad del hilo.
Quiero que esto evite el acceso de información a la misma instancia de DB. Sin embargo, ahora estoy seguro de si el siguiente código impide que getObjectById
se invoque para todas las clases cuando una clase en particular lo invoca.
public class Utils {
public static synchronized Object getObjectById (Class objclass, Long id) {
// call hibernate class
Session session = new Configuration().configure().buildSessionFactory().openSession();
Object obj = session.load(objclass, id);
session.close();
return obj;
}
// other static methods
}
For a class (static) method, the monitor associated with the Class object for the method's class is used. For an instance method, the monitor associated with this (the object for which the method was invoked) is used.
tanto, si un subproceso ingresa a un método estático, el mismo objeto devuelto por Object # getClass está bloqueado. Otros hilos aún pueden acceder a los métodos de instancia.Class
objeto, instanciado por uno de los cargadores de clases de máquinas virtuales. Como todos los objetos, este objeto también tiene unMonitor
asociado. Y este monitor es lo que se está bloqueando.Para abordar la pregunta de manera más general ...
Tenga en cuenta que usar métodos sincronizados en realidad es solo una forma abreviada (suponga que la clase es SomeClass):
es lo mismo que
y
es lo mismo que
Puede usar cualquier objeto como cerradura. Si desea bloquear subconjuntos de métodos estáticos, puede
(para métodos no estáticos, querrá hacer que los bloqueos sean campos no estáticos)
fuente
Los métodos estáticos usan la clase como el objeto para el bloqueo, que es Utils.class para su ejemplo. Entonces sí, está bien.
fuente
static synchronized
significa mantener el bloqueo en elClass
objeto de la clase donde comosynchronized
significa mantener el bloqueo en el objeto de esa clase. Eso significa que si está accediendo a un método sincronizado no estático en un hilo (de ejecución) aún puede acceder a un método sincronizado estático usando otro hilo.Por lo tanto, acceder a dos métodos del mismo tipo (ya sea dos métodos estáticos o dos no estáticos) en cualquier momento por más de un hilo no es posible.
fuente
¿Por qué quiere exigir que solo un subproceso pueda acceder a la base de datos al mismo tiempo?
Es el trabajo del controlador de la base de datos implementar cualquier bloqueo necesario, suponiendo que
Connection
que solo se use un subproceso a la vez!Lo más probable es que su base de datos sea perfectamente capaz de manejar múltiples accesos paralelos
fuente
Si tiene que ver con los datos de su base de datos, ¿por qué no utilizar el bloqueo de aislamiento de la base de datos para lograrlo?
fuente
Para responder a su pregunta, sí: su
synchronized
método no puede ser ejecutado por más de un hilo a la vez.fuente
Cómo funciona la
synchronized
palabra clave JavaCuando agrega la
synchronized
palabra clave a un método estático, el método solo puede ser llamado por un solo hilo a la vez.En su caso, cada llamada al método:
SessionFactory
Session
Sin embargo, estos fueron sus requisitos:
getObjectById
se llame para todas las clases cuando una clase particular lo llamaEntonces, incluso si el
getObjectById
método es seguro para subprocesos, la implementación es incorrecta.SessionFactory
mejores prácticasEl
SessionFactory
es seguro para subprocesos, y es un objeto muy costoso crear, ya que necesita para analizar las clases de entidad y construir la representación interna entidad metamodelo.Por lo tanto, no debe crear la llamada
SessionFactory
a cadagetObjectById
método.En su lugar, debe crear una instancia singleton para ello.
El
Session
siempre debe estar cerradoNo cerró el
Session
en unfinally
bloque, y esto puede filtrar recursos de la base de datos si se produce una excepción al cargar la entidad.Según el
Session.load
método, JavaDoc podría arrojar unHibernateException
si la entidad no se puede encontrar en la base de datos.Es por eso que necesita usar un
finally
bloque para cerrarSession
, como este:Prevención de acceso multihilo
En su caso, quería asegurarse de que solo un hilo tenga acceso a esa entidad en particular.
Pero la
synchronized
palabra clave solo evita que dos hilos llamen algetObjectById
mismo tiempo. Si los dos hilos llaman a este método uno después del otro, aún tendrá dos hilos usando esta entidad.Entonces, si desea bloquear un objeto de base de datos dado para que ningún otro hilo pueda modificarlo, entonces necesita usar bloqueos de base de datos.
La
synchronized
palabra clave solo funciona en una sola JVM. Si tiene varios nodos web, esto no impedirá el acceso de subprocesos múltiples en varias JVM.Lo que debe hacer es usar
LockModeType.PESSIMISTIC_READ
oLockModeType.PESSIMISTIC_WRITE
aplicar los cambios a la base de datos, de esta manera:Entonces, esto es lo que hice:
EntityTransaction
y comencé una nueva transacción de base de datosPost
entidad mientras mantenía un bloqueo en el registro de la base de datos asociadaPost
entidad y comprometí la transacción.Exception
ser arrojado, revertí la transacciónfuente