79088828

Date: 2024-10-15 07:33:11
Score: 3.5
Natty:
Report link

Normally, the output should always be 200.But the output of "totalMoney" sometimes a number less than 200. What is the issue here and how to correct it? Will somebody please help me?

Why the output of "totalMoney" sometimes a number less than 200 probably is that the stems from a lack of synchronization between the threads during the transfer process. The potential issue is in Bank::transferMoney method, where calling changeMoney on accountA and accountB separately.

void transferMoney(Account* accountA, Account* accountB, double amount) {
    accountA->changeMoney(-amount);
    accountB->changeMoney(amount);
}

This method releases the lock between the two operations, might resulting in inconsistencies in the total amount of money across the accounts.

void changeMoney(double amount) {
    unique_lock lock(mMoneyLock);
    mConditionVar.wait(lock, [this, amount] {
    return mMoney + amount > 0;
   });
   mMoney += amount;
   mConditionVar.notify_all();
}

What you can try to make transfer process is atomic. locking both accounts during the transfer

class Account {
public:
    Account(string name, double money): mName(name), mMoney(money) {};

public:
    void changeMoney(double amount) {
        unique_lock lock(mMoneyLock);
        mConditionVar.wait(lock, [this, amount] {
        return mMoney + amount >= 0;
        });
        mMoney += amount;
        mConditionVar.notify_all();
    }

    string getName() {
        return mName;
    }

    double getMoney() {
        // Locking
        unique_lock lock(mMoneyLock);
        return mMoney;
    }

    mutex& getMutex() {
        return mMoneyLock;
    }

private:
    string mName;
    double mMoney;
    mutex mMoneyLock;
    condition_variable mConditionVar;
};

Also try to use a std::scoped_lock to lock both accounts’ mutexes when performing the transfer.

class Bank {
public:
    void addAccount(Account* account) {
        mAccounts.insert(account);
    }

    void transferMoney(Account* accountA, Account* accountB, double amount) {
        // Lock both accounts
        scoped_lock lock(accountA->getMutex(), accountB->getMutex());

        accountA->changeMoney(-amount);
        accountB->changeMoney(amount);
    }

    double totalMoney() const {
        double sum = 0;
        for (auto a : mAccounts) {
            sum += a->getMoney();
        }
        return sum;
    }

private:
    set<Account*> mAccounts;
};
Reasons:
  • Blacklisted phrase (1): help me
  • RegEx Blacklisted phrase (3): please help me
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Low reputation (0.5):
Posted by: Shelton Liu