from threading import Lock from unsynced_bank_account import UnsyncedBankAccount class SyncedBankAccount(UnsynceedBankAccount): def __init__(self, balance: float = 0): super().__init__(balance) self.mutex = Lock() def deposit(self, amount: float) -> None: self.mutex.acquire() super().deposit(amount) self.mutex.release() def withdraw(self, amount: float) -> None: self.mutex.acquire() super().withdraw(amount) self.mutex.release()
import sys import time from threading import Thread import typing as T from bank_account import BankAccount from unsynced_bank_account import UnsyncedBankAccount from synced_bank_account import SyncedBankAccount THREAD_DELAY = 1e-16 class ATM(Thread): def __init__(self, bank_account: BankAccount): super().__init__() self.bank_account = bank_account def transaction(self) -> None: self.bank_account.deposit(10) time.sleep(0.001) self.bank_account.withdraw(10) def run(self) -> None: self.transaction() def test_atms(account: BankAccount, atm_number: int = 1000) -> None: atms: T.List[ATM] = [] for _ in range(atm_number): atm = ATM(account) atms.append(atm) atm.start() for atm in atms: atm.join() if __name__ == "__main__": atm_number = 1000 sys.setswitchinterval(THREAD_DELAY) account = UnsyncedBankAccount() test_atms(account, atm_number=atm_number) print("Balance of unsynced account after concurrent transactions:") print(f"Actual : {account.balance}\nExpected: 0") account = SyncedBankAccount() test_atms(account, atm_number=atm_number) print("Balance of synced account after concurrent transactions:") print(f"Actual : {account.balance}\nExpected: 0")