Reputation: 93
In the following code snippet, I see by printing the address of Lock objects, that each process gets a copy of the LOCK object.
""" Processes and Locks """
import multiprocessing as mp
import logging
logging.basicConfig(level=logging.DEBUG,
format='(%(processName)-10s) (%(threadName)-9s) %(message)s',)
def increase_value(iterations, value, lock):
"""Increase a shared variable"""
print(hex(id(lock)))
for _ in range(iterations):
lock.acquire()
value.value = value.value + 1
lock.release()
def decrease_value(iterations, value, lock):
"""Decrease a shared variable"""
print(hex(id(lock)))
for _ in range(iterations):
lock.acquire()
value.value -= 1
lock.release()
if __name__ == "__main__":
ITERATIONS = 100000
SHARED_VALUE = mp.Value('i', 0)
LOCK = mp.Lock()
print(hex(id(LOCK)))
t1 = mp.Process(target=increase_value,
args=(ITERATIONS, SHARED_VALUE, LOCK))
t2 = mp.Process(target=decrease_value,
args=(ITERATIONS, SHARED_VALUE, LOCK))
t1.start()
t2.start()
t1.join()
t2.join()
logging.debug("SHARED VALUE %d", SHARED_VALUE.value)
Why does that work? lock.acquire should make sense if they refer to the same lock. What am I missing?
Upvotes: 0
Views: 750
Reputation: 298166
lock.acquire
should make sense if they refer to the same lock
They do refer to the same lock, just not to the same Python object (whatever that means across Python processes).
Pretend you have this very poorly designed lock:
import os
import time
class VeryDumbLock:
def __init__(self, filename):
self.filename = filename
def acquire(self):
while os.path.exists(self.filename):
time.sleep(0.1)
with open(self.filename, 'w'):
pass
def release(self):
os.remove(self, self.filename)
If you create foo = VeryDumbLock('/tmp/lock')
and bar = VeryDumbLock('/tmp/lock')
in two different processes, both of them really are the same lock, even though they are clearly different objects residing at different addresses in memory.
The actual mechanism that the lock object implements in the background is the only thing you need to care about.
Upvotes: 1