withdrawやdepositを同時に行った場合、データの不整合が発生する可能性がある。これをデータの競合状態という。
class BankAccount(ABC): balance: float def __init__(self, balance: float = 0): self.balance: float = balance # @abstractmethod def deposit(self, amount: float) -> None: ... # @abstractmethod def withdraw(self, amount: float) -> None: ...
import sys import time from threading import Thread import typing as T from bank_account import BankAccount from unsynced_bank_account import UnsyncedBankAccount 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")
from bank_account import BankAccount class UnsyncedBankAccount(BankAccount): def deposit(self, amount: float) -> None: if amount > 0: self.balance += amount else: raise ValueError("You can't deposit a negative amount of money") def withdraw(self, amount: float) -> None: if 0 < amount <= self.balance: self.balance -= amount else: raise ValueError("Account does not have sufficient funds")