For concurrency/multithreading learning purposes, I am developing a small money transfer API which will be concurrently invoked by several users. My "database" is a ConcurrentHashMap<String, Double>
, which key/value pair represents an account id and its current balance.
I know that single operations of a ConcurrentHashMap (get()
, put()
etc.) are thread-safe, but a withdraw/deposit method would have several method calls that would ultimately make it not thread-safe.
My problem: how to design my withdraw/deposit methods to be thread-safe? At first, I thought about making them synchronized
, but that doesn't make any sense as I would be throwing away the fine grained built-in mechanism of synchronization of the ConcurrentHashMap
.
These are both my withdraw and deposit methods (don't worry about Double
for money here, that's irrelevant in this context):
private void deposit(ConcurrentHashMap<String, Double> myDatabase, String fromAccountId, String toAccountId, double amount) {
if(myDatabase.get(fromAccountId) < amount) {
throw new MonetaryOperationViolation("Insufficient funds to perform this operation");
}
//Add the amount to the receiver's account
myDatabase.replace(toAccountId, myDatabase.get(toAccountId), c.get(toAccountId) + amount); //key, oldValue, newValue
//Withdraw it from the sender's account
withdraw(myDatabase, fromAccountId, amount);
}
private void withdraw(ConcurrentHashMap<String, Double> myDatabase, String accountId, double amount) {
if(myDatabase.get(accountId) < amount) {
throw new MonetaryOperationViolation("Insufficient funds to perform this operation");
}
myDatabase.replace(accountId, myDatabase.get(accountId), myDatabase.get(accountId) - amount);
}
I hope I've made myself clear regarding my issue. Any help would be truly appreciated.