why there is no race condition using global python variable

Question:

I have the following code:

from threading import Thread, Lock

value = 0

def adder(amount, repeats):
    global value
    for _ in range(repeats):
        value += amount
 
def subtractor(amount, repeats):
    global value
    for _ in range(repeats):
        value -= amount

def main():
    value = 0

    adder_thread = Thread(target=adder, args=(100, 1000000))
    subtractor_thread = Thread(target=subtractor, args=(100, 1000000))

    subtractor_thread.start()
    adder_thread.start()

    print('Waiting for threads to finish...')

    adder_thread.join()
    subtractor_thread.join()

    print(f'Value: {value}')

if __name__ == '__main__':
    main()

What I don’t understand is why I do not have a race condition here? We have global variable, two threads, it suppose to give different values when subtracting and adding, but for me it’s always giving 0. How to make race condition in this example? Is the global variable protected with some synchronisation primitive?

Asked By: Oleg

||

Answers:

The problem of your code is that when you run both threads, it is adding and subtracting the same amount same number of times on the same variable. What result other that 0 will you expect? I suggest having two variables instead of one variable. One for add and one for subtract. Your code should look something like this:

from threading import Thread, Lock

add_value = 0
subtract_value = 0

def adder(amount, repeats):
    global add_value
    for _ in range(repeats):
        add_value += amount
    print(add_value)
 
def subtractor(amount, repeats):
    global subtract_value
    for _ in range(repeats):
        subtract_value -= amount
    print(subtract_value)
        

def main():
    adder_thread = Thread(target=adder, args=(100, 1000000))
    subtractor_thread = Thread(target=subtractor, args=(100, 1000000))

    subtractor_thread.start()
    adder_thread.start()

    print('Waiting for threads to finish...')

    adder_thread.join()
    subtractor_thread.join()

if __name__ == '__main__':
    main()

Result:

Waiting for threads to finish...
-100000000
100000000
Answered By: ss3387

your code can create race condition.
but the value that you are printing is zero because of this line.

def main():
    value = 0

you declare a value in main which you try to print and it won’t access the global one.
try this:

def main():
    global value
    value = 0
Answered By: Mojtaba