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