Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

Example: Bank Account Program

Give Feedback

In this lesson, you’ll create a bank account program that demonstrates a race condition. If you download the sample code, you can get your own copy of 09-account.py:

Download

Sample Code (.zip)

12.9 KB

To learn more, you can also check out the documentation for concurrent.futures.Executor.submit as well as the software section of the Wikipedia page on race conditions.

fiy the wikipedia links to the Executor.submit python doc

malbert137 on June 1, 2020

Presumably at the exit of the context manager, the thread pool joins all of the “submitted” threads?

dlasusa0 on Oct. 7, 2020

Win10 Python 3.8.5

Not sure if anything changed, but running the 09-account.py file from the download zip (and it looks the same as the ending code in the video), I get a different result:

starting with balance of 100  
deposit thread updating...  
withdrawal thread updating...  
withdrawal thread finishing...  
deposit thread finishing...  
ending balance of 150  

I can see why it’s 150 (the deposit thread is finishing last and therefore setting the account.balance to 150, but I’m not sure why this is happening.

The code as it’s being run:

import concurrent.futures
import time

class Account:
    def __init__(self):
        self.balance = 100 # shared data
    def update(self, transaction, amount):
        print(f'{transaction} thread updating...')
        local_copy = self.balance
        local_copy += amount
        time.sleep(2)
        self.balance = local_copy
        print(f'{transaction} thread finishing...')

if __name__ == '__main__':
    account = Account()
    print(f'starting with balance of {account.balance}')
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as ex:
        for transaction, amount in [('deposit', 50), ('withdrawal', -150)]:
            ex.submit(account.update, transaction, amount)
    print(f'ending balance of {account.balance}')

dlasusa0 on Oct. 7, 2020

Nevermind. I found by adjusting the sleep time (I tried both 2 and 5) and running the code multiple times it would sometimes be 150 and sometimes -50. So I’m guessing the issue is scheduling with a busy cpu?

Become a Member to join the conversation.