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")