Search code examples
pythonglobal-variablespython-multithreading

How can i use concurrent functions to change a global variable?


How could i edit my code so i can run functions at the same time using multiprocessing or something similar and edit the value of a global variable in the same way like i would with a regular function? This is an examples showing the code that i have been using:

import multiprocessing
from multiprocessing import Process

def runInParallel(*fns):

  

  proc = []

  for fn in fns:

    p = Process(target=fn)

    p.start()

    proc.append(p)

  for p in proc:

    p.join()


variable = 1



def changethevariable():
  global variable
  variable= variable +1
  return variable
   
def changethevariable_again():
  global variable
  variable= variable +3
  return variable

runInParallel(changethevariable_again,changethevariable)
print(variable)

Solution

  • There are a number of things wrong.

    1. They way your code is written, every process has its own copy of variable. There is no reason that changing the value of variable in one process will cause it to change in another. This is one of the big differences between multiprocessing and multithreading.

    2. Even when you do have a shared variable between to processes (or even two threads), update operations are race prone. You are performing x += 1 in one process and x += 3 in the other. Imagine both threads read x at the same time, one increments the value by 1, one increments it by 3, and then both write it back. The result will be that only one of the increments happens.

    3. When running multiprocessing, all code that is to happen only in the main thread must be done under the protection of if __name__ == '__main__'. In your code, every process is calling runInParallel.

    So. You need a shared variable. You need locks. And you need to put your initialization code inside a main().

    import multiprocessing
    from multiprocessing import Process
    
    def runInParallel(*fns):
        global variable
        proc = []
        for fn in fns:
            p = Process(target=fn, args=(variable,))
            p.start()
            proc.append(p)
    
        for p in proc:
            p.join()
    
    def changethevariable(variable):
        with variable.get_lock():
            variable.value = variable.value + 1
    
    def changethevariable_again(variable):
        with variable.get_lock():
            variable.value = variable.value + 3
    
    def main():
        global variable
        variable = multiprocessing.Value('i', 1)
        runInParallel(changethevariable_again, changethevariable)
        print(variable.value)
    
    if __name__ == '__main__':
        main()