I have a question about how @Transactional annotation alone manages code and transactions execution. Given a correctly setup Spring application and the following code:
@Transactional
public void withdraw(int amount) {
if(isEnoughFunds(amount)) {
decreaseFunds(amount);
}
}
Is it possible for the following scenario to occur:
- funds == 100; amount == 100
- thread A enters withdraw / transaction A starts
- thread A executes isEnoughFunds which evaluates to true
- thread B enters withdraw / transaction B starts
- thread B executes isEnoughFunds which evaluates to true
- thread A executes decreaseFunds / thread A locks db record
- thread B waits for thread A to commit transaction and release write lock
- thread A exits withdraw / transaction A commits
- thread B executes decreaseFunds / thread B locks db record
- thread B exits withdraw / transaction B commits
- funds == -100
If this is possible how would you prevent that?