2012-09-26 10 views
7

Ich habe eine Frage darüber, wie @Transactional Annotation allein Code und Transaktionen Ausführung verwaltet. Bei einer richtig Setup Frühling Anwendung und den folgenden Code:mit @Transactional für Thread-Sicherheit

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

Ist es möglich, dass das folgende Szenario auftreten:

  • Mittel == 100; Menge == 100
  • Thread A eintritt/A-Transaktion zurückzuziehen beginnt
  • Thread A isEnoughFunds ausführt, die
  • Thread B true ergibt tritt zurückzuziehen/B-Transaktion beginnt
  • Thread B führt isEnoughFunds die auf true
  • auswertet
  • Gewinde A führt decreaseFunds/
  • Gewinde B wartet Gewinde A A Sperren db Datensatz fädeln Transaktion zu binden und freizugeben Schreibsperre
  • Thread A Ausfahrten zurückzuziehen/A-Transaktion begeht
  • Gewinde B führt decreaseFunds/Gewinde B Schlösser
  • Gewinde B Ausgänge B verpflichtet
  • Mittel == -100

zurückzuziehen/Transaktion aufzeichnen db Wenn dies möglich ist, wie würden Sie das verhindern?

+2

Die Annotation sagt nur, um dies in eine Transaktion zu wickeln. Die Datenbankisolationsstufe bestimmt, wie viel Interleaving auftritt. –

Antwort

3

Ja, es ist möglich, abhängig von der Isolationsstufe. Um dies zu verhindern, können Sie vor dem Aufruf von ifEnoughFunds() explizit eine Lesesperre von der Datenbank erhalten. Die Sperre wird am Ende der Transaktion freigegeben. In diesem Szenario wartet Thread B immer auf das Festschreiben von Thread A-Transaktion vor dem Überprüfen.

+4

Kannst du das weiter erklären mit einem Codebeispiel wie man das im Frühjahr macht und überwintern? Danke! –