Search code examples
pythonpython-multithreading

How to synchronize threads with shared global variable in python?


i'm currently trying to unterstand threading in python and i wrote a program that ideally would have 2 threads alternating between incrementing and decrementing a global variable but no matter how i spread out the lock it inevitably becomes out of sync.

number = 0
lock = threading.Lock()
def func1():
    global number
    global lock
    while True:
        try:
            lock.acquire()
            number += 1
        finally:
            lock.release()
        print(f"number 1 is: {number}")
        time.sleep(0.1)

def func2():
    global number
    global lock
    while True:
        try:
            lock.acquire()
            number -= 1
        finally:
            lock.release()
        print(f"number 2 is: {number}")
        time.sleep(0.1)

t1 = threading.Thread(target=func1)
t1.start()

t2 = threading.Thread(target=func2)
t2.start()

t1.join()
t2.join()

the output should look something like this:

number 1 is: 1
number 2 is: 0
number 1 is: 1
number 2 is: 0
number 1 is: 1
number 2 is: 0
number 1 is: 1
number 2 is: 0

but right now it looks like this:

number 1 is: 1
number 2 is: 0
number 1 is: 1
number 2 is: 0
number 2 is: -1number 1 is: 0

number 2 is: -1number 1 is: 0

number 1 is: 1number 2 is: 0

any idea how to do this without falling out of sync?


Solution

  • thanks for all your answers, i remember seing someone in the comments mentioned using events or something like that and that solved the issue. here's the code:

    number = 0
    event_number = threading.Event()
    event_number.clear()
    
    def func1():
        global number
        global event_number
        while True:
            if not event_number.is_set():
                number += 1
                print(f"func 1 is {number}")
                event_number.set()
            else:
                pass
            time.sleep(2)
    
    def func2():
        global number
        global event_number
        while True:
            if event_number.is_set():
                number -= 1
                print(f"func 2 is {number}")
                event_number.clear()
            else:
                pass
            time.sleep(2)
    
    t1 = threading.Thread(target=func1)
    t2 = threading.Thread(target=func2)
    
    t1.start()
    t2.start()
    
    t1.join()
    t2.join()
    

    now i notice that sometimes one of the loops will either not wait it's alloted time and print right away or wait double the time but at least the number only stays within those 2 values.