Skip to content

Instantly share code, notes, and snippets.

@Verdagon
Created January 12, 2022 20:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Verdagon/ef69b4c5e54a683ecd6a8afb715c3a80 to your computer and use it in GitHub Desktop.
Save Verdagon/ef69b4c5e54a683ecd6a8afb715c3a80 to your computer and use it in GitHub Desktop.
Example of a data race in Python
# Does Python have data races?
#
# As we've seen, Java can have data races, according to
# https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html
# It says an example of a data race is when:
# - there is a write in one thread,
# - a read of the same variable by another thread,
# - and the write and read are not ordered by synchronization.
#
# This program attempts to cause a data race in Python.
from threading import Thread
from time import sleep
counter = 0
def increase():
global counter
for i in range(0, 100000):
counter = counter + 1
threads = []
for i in range(0, 400):
threads.append(Thread(target=increase))
for thread in threads:
thread.start()
for thread in threads:
thread.join()
print(f'Final counter: {counter}')
# A few trials from my computer (Mac, 2.6 GHz 6-Core i7):
# Final counter: 31735072
# Final counter: 32829326
# Final counter: 31496003
#
# We conclude that yes, Python has data races.
@kprotty
Copy link

kprotty commented Sep 21, 2022

This seems like more of a race condition than a data race. You can get similar results in C/C++/Rust even when not hitting data races due to the operation as a whole not being atomic w.r.t concurrent thread execution:

atomic_store_explicit(&x, atomic_load_explicit(&x, memory_order_relaxed) + 1, memory_order_relaxed);

@Volume999
Copy link

If you're (like me) struggling to recreate this, here's an easy change to show the preemptive multitasking creating race conditions (works every time for me):

def increase():
    global counter
    for i in range(0, 10):
        val = counter
        sleep(0.0001)
        counter = val + 1

You can also play around with sys.setswitchinterval() that changes the interval for thread switching

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment