You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Improve documentation on multiprocessing synchronization-between-processes #116526
when running the provided example locally, unlike other examples on this page which can print valid stdout, the code in this section will only print out the error below, which is caused by not providing the Process.join() call at the end.
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/Users/chhan/.pyenv/versions/3.12.2/lib/python3.12/multiprocessing/spawn.py", line 122, in spawn_main
exitcode = _main(fd, parent_sentinel)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/chhan/.pyenv/versions/3.12.2/lib/python3.12/multiprocessing/spawn.py", line 132, in _mainself= reduction.pickle.load(from_parent)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/chhan/.pyenv/versions/3.12.2/lib/python3.12/multiprocessing/synchronize.py", line 115, in __setstate__self._semlock = _multiprocessing.SemLock._rebuild(*state)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^FileNotFoundError: [Errno 2] No such file or directory
To be honest this is a pretty bad example to begin with - because you won't notice any difference if you simply remove the lock so it's pretty confusing when users try it out. The stdout is buffered in most environments and won't flush until seeing a newline. We should probably change this to something more obvious - multiple prints maybe (building a triangle?).
The exception mentioned in this issue can be reproduced with spawn, but might be hard to repro with fork as fork is too fast.
Hey @gaogaotiantian , thanks for your reply. I think your point makes sense, and it still confuses me when reading it as well. Either with or without the lock, the example doesn't seem to emphasize what difference this lock brings. Tbh, my original intent was to just complete the example to remove some exceptions, now I think maybe a new example is needed.
one quick example I could think of is as below, we increment a value 3 times in a process.
importmultiprocessing# Function to be executed by each processdefincrement_counter(counter, lock, process_id):
lock.acquire()
for_inrange(3):
counter.value+=1print(f"Counter value: {counter.value} incremented by the {process_id} process")
lock.release()
if__name__=="__main__":
# Shared counter valuecounter=multiprocessing.Value('i', 0)
# Creating a Locklock=multiprocessing.Lock()
# Creating processesprocesses= []
forjinrange(4): # Creating 4 processesp=multiprocessing.Process(target=increment_counter, args=(counter, lock, j))
processes.append(p)
p.start()
# Waiting for all processes to finishforpinprocesses:
p.join()
# Output the final value of the counterprint("Final counter value:", counter.value)
with the lock, the value will consecutively be incremented by the same process, and the example will output something like this
Counter value: 1 incremented by the 1 process
Counter value: 2 incremented by the 1 process
Counter value: 3 incremented by the 1 process
Counter value: 4 incremented by the 0 process
Counter value: 5 incremented by the 0 process
Counter value: 6 incremented by the 0 process
Counter value: 7 incremented by the 2 process
Counter value: 8 incremented by the 2 process
Counter value: 9 incremented by the 2 process
Counter value: 10 incremented by the 3 process
Counter value: 11 incremented by the 3 process
Counter value: 12 incremented by the 3 process
Final counter value: 12
if we remove the lock-related code,
importmultiprocessing# Function to be executed by each processdefincrement_counter(counter, process_id):
for_inrange(3):
counter.value+=1print(f"Counter value: {counter.value} incremented by the {process_id} process")
if__name__=="__main__":
# Shared counter valuecounter=multiprocessing.Value('i', 0)
# Creating processesprocesses= []
forjinrange(4): # Creating 4 processesp=multiprocessing.Process(target=increment_counter, args=(counter, j))
processes.append(p)
p.start()
# Waiting for all processes to finishforpinprocesses:
p.join()
# Output the final value of the counterprint("Final counter value:", counter.value)
it will randomly print out some duplicates like below, eventually not even reaching 12.
Counter value: 1 incremented by the 3 process
Counter value: 1 incremented by the 2 process
Counter value: 1 incremented by the 0 process
Counter value: 2 incremented by the 1 process
Counter value: 3 incremented by the 3 process
Counter value: 4 incremented by the 2 process
Counter value: 4 incremented by the 0 process
Counter value: 4 incremented by the 1 process
Counter value: 5 incremented by the 3 process
Counter value: 6 incremented by the 2 process
Counter value: 6 incremented by the 0 process
Counter value: 6 incremented by the 1 process
Final counter value: 6
Activity
pythonGH-116526 patch Synchronization between processes example
pythonGH-116526 patch Synchronization between processes example
pythonGH-116526 patch Synchronization between processes example
gaogaotiantian commentedon Mar 9, 2024
To be honest this is a pretty bad example to begin with - because you won't notice any difference if you simply remove the lock so it's pretty confusing when users try it out. The stdout is buffered in most environments and won't flush until seeing a newline. We should probably change this to something more obvious - multiple prints maybe (building a triangle?).
The exception mentioned in this issue can be reproduced with spawn, but might be hard to repro with fork as fork is too fast.
HCharlie commentedon Mar 10, 2024
Hey @gaogaotiantian , thanks for your reply. I think your point makes sense, and it still confuses me when reading it as well. Either with or without the lock, the example doesn't seem to emphasize what difference this lock brings. Tbh, my original intent was to just complete the example to remove some exceptions, now I think maybe a new example is needed.
HCharlie commentedon Mar 10, 2024
one quick example I could think of is as below, we increment a value 3 times in a process.
with the lock, the value will consecutively be incremented by the same process, and the example will output something like this
if we remove the lock-related code,
it will randomly print out some duplicates like below, eventually not even reaching 12.
wdyt?
serhiy-storchaka commentedon May 30, 2026
This looks too complicated for a simple example. Would not it be enough to use several prints?