"""
This file shows a race condition using Python threads.

Because Python has a Global Interpeter Lock, race conditions are only seen
if each thread has to do non-trivial interdependant work in parallel.
We achieve that by repeated counting: 1, 1 2, 1 2 3, 1 2 3 4, and so on,
printing out each time we reset. This reliably manifests a race condition
after only a dozen or so resets, where simpler functions I tried needed
many more iterations.

n = the number of total counting steps to make across all threads
tcount = the number of threads to run
"""


n = 2000
tcount = 1



from threading import Thread

small = 0
big = 0

def step():
    global small, big
    if small >= big:
        big += 1
        print('big =', big)
        small = 0
    else:
        small += 1

def tfunc(n):  
    for s in range(n):
        step()


threads = [Thread(target=tfunc, args=[n//tcount]) for tidx in range(tcount)]
for t in threads: t.start()
for t in threads: t.join()

print('small =', small)
print('check:', big*(big+1)//2 + small)