Skip to content
Advertisement

Adding money from one account to another using multithreading

I have 2 accounts and 2 threads. 1 thread transfers money from 1 account to 2 account, 2 thread transfers money from 2 account to 1 account, if of course there is enough money. I need to realize the deadlock situation and solve the deadlock situation confirming safe transfer. Here is what I have for now:

Account.java

JavaScript

Main.java

JavaScript

TransferThread.java

JavaScript

I decided to put synchronized to both methods deposit and withdraw for safe transfering. But doubt with the method run realization. Do I have a rigth implementation? If not, explanation and correction will be appreciated.

Advertisement

Answer

Your solution is not vulnerable to deadlocks because the TransferThread instances are never going to hold more than one lock at a time.

However, I don’t think it is a correct solution. The problems are here:

JavaScript

The first problem is you are transferring money in the wrong direction! Money should go from the from account to the to account. But you are depositing money into the from account and withdrawing money from the to account.

Customers won’t be happy about that.

Lets fix that:

JavaScript

The problem now is that we are depositing before we withdraw. Why is that a problem? Because between the from.getBalance() and from.withdraw(...) calls, another thread could make a withdrawl from the from account. That could mean that our from.withdraw(amount) call could fail. But we’ve already deposited the money into the to account. Ooops!

Lets fix that:

JavaScript

Close …

What happens if we get a power dip at the point marked HERE? Well, if we dealing with real bank accounts, then we would actually be storing the information in a database. So the values currently in the accounts would be preserved. But at the point labelled HERE we would have withdrawn money from one account and not deposited it in the other one. What happens to that money? Poof! Gone!

Does that matter? Well it depends on how we frame the requirements. Assuming that it is OK to represent the bank accounts as (only) in memory objects, I’d say that we can ignore that nicety of surviving power failure during a transfer. The power failure would blow away the accounts as well.

Close enough is good enough, here. But we can do slightly better. As we noted, the value in the from account can change between the getBalance() and withdraw() calls, so that the withdraw() could fail. But when you think about it from.withdraw is just testing from.getBalance() < 0 anyway. So, we can just get rid of the test:

JavaScript

If the from.withdraw(amount) is going to overdraw the account, it will fail with an exception. And we won’t then do the to.deposit(amount) call.


Now we could try to implement a transfer method that takes two accounts as arguments, and transfers money from one to the other as an atomic operation. You could conceivably do this by acquiring locks on both accounts before doing the transfer; e.g. like this:

JavaScript

(I’m deliberately ignoring the exceptions and exception handling.)

But now we have to worry about deadlock. For example, if one thread tries to transfer money from A to B, and another simultaneously transfer money from B to A.

There are ways to deal with this:

  • One way is to the Lock API and acquire the locks with a timeout to detect deadlock.

  • Another way is write the transfer method to acquire the account locks in the same order when doing transfer(A,B) and transfer(B,A). For example, assuming that Account objects have unique account numbers, then lock the Account with the lower account number first.

    JavaScript
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement