2012-09-26 19 views
7

Tengo una pregunta sobre cómo la anotación @Transactional solo administra el código y la ejecución de transacciones. Dada una aplicación Primavera correctamente la instalación y el siguiente código:usando @Transactional para seguridad de hilos

@Transactional 
public void withdraw(int amount) { 
    if(isEnoughFunds(amount)) { 
     decreaseFunds(amount); 
    } 
} 

¿Es posible que el siguiente escenario que se produzca:

  • fondos == 100; cantidad == 100
  • hilo A entra retirar/transacción A empieza
  • hilo A ejecuta isEnoughFunds que evalúa a verdadero
  • hilo B entra retirar/transacción B comienza
  • hilo B realiza isEnoughFunds que evalúa a verdadero
  • hilo a ejecuta decreaseFunds/Autor Un registro cerraduras db
  • espera hilo para el hilo B a se confirme la transacción y liberar bloqueo de escritura
  • salidas hilo a retiran/transacción a comete
  • hilo B ejecuta decreaseFunds/cierres de rosca B DB grabar
  • salidas hilo B se retiran/transacción B hace
  • fondos == -100

Si esto es posible ¿cómo evitar que eso?

+2

la anotación simplemente dice que envuelva esto en una transacción. el nivel de aislamiento de la base de datos determina cuánto entrelazado se produce. –

Respuesta

3

Sí, es posible, dependiendo del nivel de aislamiento. Para evitarlo, puede obtener explícitamente un bloqueo de lectura de la base de datos antes de llamar a ifEnoughFunds(). El bloqueo se liberará al final de la transacción. En este escenario, el hilo B siempre esperará a que la transacción A del hilo se confirme antes de verificar.

+4

¿Puede explicar esto más a fondo con un ejemplo de código de cómo hacer esto en primavera e hibernar? ¡gracias! –

Cuestiones relacionadas