Reputation: 789
I have a program where 4 threads are running concurrently withdraw / deposit operations on a "bank account"
I am supposed to synchronize threads with atomics (school task). Im using currently compare_exchange and it works on deposit (addition) because it does not matter when addition is done.
However there is a problem with withdraw since account cannot go negative.
Example. Lets say account balance is 300, thread1 wants to withdraw 200, checks that its ok and proceeds to withdraw function. Using compare_exchange , excpected value is 300, and new one is 300-200. Thread2 also wants to withdraw 200 from account at the same time, both threads check ok and enter withdraw, doesnt matter now which one makes it first but second one will have now have expected go from 300 to 100, and then does 100 - 200 and we reach a situation where account is negative.
I ran a large transaction number and it does occur I currently have this piece of code for withdraw operation
void withdraw(int amount)
{
float old = m_iBalance.load();
while(!m_iBalance.compare_exchange_weak(old, old - amount))
{
//
}
if (m_iBalance < 0 )
{
cout << m_iBalance << endl;
}
}
How can I use atomic as a mutex to allow only one thread to access withdraw function at a time ?
Upvotes: 0
Views: 415
Reputation: 531
Is this what you want?
class Account
{
public:
Account(double balance)
: m_balance(balance)
{
}
void Deposit(double amount)
{
double old_amount, new_amount;
do {
old_amount = m_balance.load();
new_amount = old_amount + amount;
} while (!m_balance.compare_exchange_weak(old_amount, new_amount));
}
bool Withdraw(double amount)
{
double old_amount, new_amount;
do {
old_amount = m_balance.load();
new_amount = old_amount - amount;
if (new_amount < 0) return false;
} while (!m_balance.compare_exchange_weak(old_amount, new_amount));
return true;
}
double Amount() const { return m_balance.load(); }
protected:
std::atomic<double> m_balance;
};
Upvotes: 1