2016-12-01 34 views
1

假設我有兩個函數如下所示。第一個(use_stuff)可以被許多線程用來做一些計算,而第二個(clean_stuff_cache)可以偶爾在單獨的線程中調用,當我們需要更新緩存時。我應該使用哪種同步機制(我稱之爲counter)來確保clean_stuff_cache將被阻塞,直到所有線程完成use_stuff例程。使用哪種機制來正確釋放許多線程獲取的資源

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] 
+0

你可以試試信號,當線程要刷新等等緩存,發送信號給其他線程,這樣他們可以退出/ sotp /暫停,清理緩存後,只需發送另一個信號重新啓動 – Raskayu

回答

1

可以使用Semaphore對象這裏有Lock結合起來。信號量允許有一個同步計數器,阻止如果你試圖獲取,如果當它爲0
所以,如果counter = Semaphore(0)lock = Lock()則:

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() 
+0

我採取了你的方法(它工作正常),並且也構建了我自己的來創建可重用的裝飾器(參見他們在這裏https://gist.github.com/tsionyx/889a867f8d78823cbcf495523da6ab0c) – tsionyx