2012-09-26 39 views
7

我有一個關於@Transactional註釋如何管理代碼和事務執行的問題。給定一個正確安裝Spring應用程序和下面的代碼:使用@Transactional進行線程安全

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

是否有可能出現以下情況:

  • 資金== 100;量== 100
  • 線程A進入退出/交易A開始
  • 線程A執行isEnoughFunds其評估爲真
  • 線程B進入退出/交易B開始
  • 線程B執行isEnoughFunds其評估爲真
  • 線程A執行decreaseFunds /線程A鎖定了數據庫記錄
  • 線程B等待線程A提交事務,並釋放寫鎖
  • 線程A退出抽取/事務A提交
  • 線程B執行decreaseFunds /線程B鎖定數據庫記錄
  • 線程B出口抽取/事務B提交
  • 資金== -100

如果這是可能的,你將如何避免呢?

+2

註解只是說在交易中包裝這個。數據庫隔離級別決定了發生多少交織。 –

回答

3

是的,這可能取決於隔離級別。爲了防止它,你可以在調用ifEnoughFunds()之前明確地從數據庫獲得一個讀鎖。鎖定將在交易結束時釋放。在這種情況下,線程B將始終等待線程的A事務在檢查之前提交。

+4

你可以用一個代碼示例進一步解釋如何在春季和冬眠期間做到這一點?謝謝! –