Нам нужно убедиться, что несколько потоков не могут изменить баланс одновременно.
Функция deposit()
, хотя кажется, что это один шаг, является многошаговой операцией.
old_balance = self.balance
new_balance = old_balance + deposit
self.balance = new_balance
Если переключение потоков происходит в середине депозита, это может повредить данные.
Например, предположим, что поток 1 вызывает deposit(10)
, а поток 2 вызывает deposit(20)
, начальный баланс равен 100
# Inside thread 1
old_balance1 = self.balance
new_balance1 = old_balance1 + 10
# Thread switches to thread 2
old_balance2 = self.balance
new_balance2 = old_balance2 + 20
self.balance = new_balance2 # balance = 120
# Thread switches back to thread 1
self.balance = new_balance1 # balance = 110
Здесь окончательный баланс равен 110
, тогда как он должен был быть 130
.
Решение состоит в том, чтобы предотвратить одновременную запись в переменную balance
двух потоков. Для этого мы можем использовать Lock
s.
import threading
class BankAccount:
def open(self):
self.balance = 0
# initialize lock
self.lock = threading.Lock()
def deposit(self, val):
# if another thread has acquired lock, block till it releases
self.lock.acquire()
self.balance += val
self.lock.release()
def withdraw(self, val):
self.lock.acquire()
self.balance -= val
self.lock.release()
def get_balance(self):
return self.balance