Python multi process synchronization Lock Semaphore Event instances

  • 2020-04-02 14:24:41
  • OfStack

The synchronization method is basically the same as multithreading.

1) the Lock

Locks can be used to avoid access conflicts when multiple processes need to access a Shared resource.


import multiprocessing
import sys def worker_with(lock, f):
    with lock:
        fs = open(f,"a+")
        fs.write('Lock acquired via withn')
        fs.close()
       
def worker_no_with(lock, f):
    lock.acquire()
    try:
        fs = open(f,"a+")
        fs.write('Lock acquired directlyn')
        fs.close()
    finally:
        lock.release() if __name__ == "__main__":     f = "file.txt"
 
    lock = multiprocessing.Lock()
    w = multiprocessing.Process(target=worker_with, args=(lock, f))
    nw = multiprocessing.Process(target=worker_no_with, args=(lock, f))     w.start()
    nw.start()     w.join()
    nw.join()

In the above example, if two processes are not using a lock to synchronize, their writing to the same file can be messy.

2) Semaphore

Semaphore is used to control the number of accesses to Shared resources, such as the maximum number of connections to a pool.


import multiprocessing
import time def worker(s,i):
    s.acquire()
    print(multiprocessing.current_process().name + " acquire")
    time.sleep(i)
    print(multiprocessing.current_process().name + " release")
    s.release() if __name__ == "__main__":
 
    s = multiprocessing.Semaphore(2)
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(s,i*2))
        p.start()

The use of semaphore in the above example restricts the execution of up to two processes simultaneously.

3) the Event

Event is used to realize synchronous communication between processes.


import multiprocessing
import time def wait_for_event(e):
    """Wait for the event to be set before doing anything"""
    print ('wait_for_event: starting')
    e.wait()
    print ('wait_for_event: e.is_set()->' + str(e.is_set())) def wait_for_event_timeout(e, t):
    """Wait t seconds and then timeout"""
    print ('wait_for_event_timeout: starting')
    e.wait(t)
    print ('wait_for_event_timeout: e.is_set()->' + str(e.is_set()))
if __name__ == '__main__':
    e = multiprocessing.Event()
    w1 = multiprocessing.Process(name='block',
                                 target=wait_for_event,
                                 args=(e,))
    w1.start()     w2 = multiprocessing.Process(name='non-block',
                                 target=wait_for_event_timeout,
                                 args=(e, 2))
    w2.start()     time.sleep(3)
    e.set()
    print ('main: event is set')
   
#the output is:
#wait_for_event_timeout: starting
#wait_for_event: starting
#wait_for_event_timeout: e.is_set()->False
#main: event is set
#wait_for_event: e.is_set()->True


Related articles: