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 synchronizedes 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 getObjectByIdse 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.Classobjeto, instanciado por uno de los cargadores de clases de máquinas virtuales. Como todos los objetos, este objeto también tiene unMonitorasociado. 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 synchronizedsignifica mantener el bloqueo en elClassobjeto de la clase donde comosynchronizedsignifica 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
Connectionque 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
synchronizedmétodo no puede ser ejecutado por más de un hilo a la vez.fuente
Cómo funciona la
synchronizedpalabra clave JavaCuando agrega la
synchronizedpalabra 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:
SessionFactorySessionSin embargo, estos fueron sus requisitos:
getObjectByIdse llame para todas las clases cuando una clase particular lo llamaEntonces, incluso si el
getObjectByIdmétodo es seguro para subprocesos, la implementación es incorrecta.SessionFactorymejores prácticasEl
SessionFactoryes 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
SessionFactorya cadagetObjectByIdmétodo.En su lugar, debe crear una instancia singleton para ello.
El
Sessionsiempre debe estar cerradoNo cerró el
Sessionen unfinallybloque, y esto puede filtrar recursos de la base de datos si se produce una excepción al cargar la entidad.Según el
Session.loadmétodo, JavaDoc podría arrojar unHibernateExceptionsi la entidad no se puede encontrar en la base de datos.Es por eso que necesita usar un
finallybloque 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
synchronizedpalabra clave solo evita que dos hilos llamen algetObjectByIdmismo 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
synchronizedpalabra 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_READoLockModeType.PESSIMISTIC_WRITEaplicar los cambios a la base de datos, de esta manera:Entonces, esto es lo que hice:
EntityTransactiony comencé una nueva transacción de base de datosPostentidad mientras mantenía un bloqueo en el registro de la base de datos asociadaPostentidad y comprometí la transacción.Exceptionser arrojado, revertí la transacciónfuente