Reputation: 1669
Suppose I have two functions presented below. The first one (use_stuff
) can be used by many threads to do some computation, while the second one (clean_stuff_cache
) can be called occasionally in separate thread when we need to update cache. Which synchronization mechanism (I call it counter
here) should I use to ensure that the clean_stuff_cache
will block until all the threads finish the use_stuff
routine.
stuff_cache = dict()
counter = ????
def use_stuff(id):
counter.acquire()
if id not in stuff_cache:
stuff_cache[id] = get_stuff(id)
# do some computation using stuff
do_stuff(stuff_cache[id])
counter.release()
def clean_stuff_cache(id):
counter.wait_until_zero()
# drop all the stuff being used
del stuff[id]
Upvotes: 1
Views: 84
Reputation: 4467
You can use a Semaphore
object here combine with a Lock
. The semaphore permits to have a synchronized counter that block if you try to acquire if when it is 0.
So if counter = Semaphore(0)
, and lock = Lock()
then:
def use_stuff(id):
# Increment number of running workers if your are not cleaning the cache
with lock:
counter.release()
..... do stuff...
# decrement number of running workers
counter.acquire()
def clean_stuff():
# counter.acquire return False if there is no worker running
while True:
lock.acquire()
if counter.acquire(False):
counter.release()
lock.release()
else:
break
# delay next loop so the check is only occasional
time.sleep(.01)
# here, no worker is running and the lock prevents new worker
# from starting so you can cleanup the cache...
... do clean up
lock.release()
Upvotes: 1