Search code examples
pythonmultithreadingparallel-processing

Using threading in Python to deposit and withdrew money from a bank account


import threading
import time

money_flag=threading.Lock()
balance = 0
nb_transaction = 999999
counter = 0

def transaction(nb_transaction, n):
    global balance
    global counter
    for _ in range(nb_transaction):
        if balance < 0:
            counter += 1
        money_flag.acquire()
        balance += n
        money_flag.release()
    
t1 = threading.Thread(target=transaction, args=(nb_transaction,1,))
t2 = threading.Thread(target=transaction, args=(nb_transaction,-1,))

t1.start()
t2.start()

t1.join()
t2.join()

print(counter)
print(balance)

In the above code, the balance can go below zero occasionally. To prevent it from being less than zero, I add a money_flag, but this does not help. How to make sure that the thread 2 function pauses when the balance is less than 0? At the end, the expected balance should be zero.


Solution

  • You should be using a condition variable, not a lock.

    cv = threading.Condition()
    
    def transaction(nb_transaction, n):
        global balance
        for _ in range(nb_transaction):
            with cv:
                cv.wait_for(lambda: balance + n >= 0)
                balance += n
                cv.notify_all()
    

    The cv.wait_for() ensures than when it returns, balance + n >= 0 is true and that it still holds the lock that it had when it tested that condition.

    The cv.notify_all() (it could probably be just cv.notify() here, but in general notify_all()` is safer) says that "things have changed" and that anyone waiting should try again.