How to do this with threading.Events :
import threading import time import logging logger=logging.getLogger(__name__) def f(resume,is_waiting,name): while True: if not resume.is_set(): is_waiting.set() logger.debug('{n} pausing...'.format(n=name)) resume.wait() is_waiting.clear() logger.info(name) time.sleep(1) def h(resume,waiters): while True: logger.debug('halt') resume.clear() for i,w in enumerate(waiters): logger.debug('{i}: wait for worker to pause'.format(i=i)) w.wait() logger.info('h begin') time.sleep(2) logger.info('h end') logger.debug('resume') resume.set() time.sleep(5) logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s %(threadName)s] %(message)s', datefmt='%H:%M:%S')
gives
[07:28:55 Thread-1] f [07:28:55 Thread-2] g [07:28:55 Thread-3] halt [07:28:55 Thread-3] 0: wait for worker to pause [07:28:56 Thread-1] f pausing... [07:28:56 Thread-2] g pausing... [07:28:56 Thread-3] 1: wait for worker to pause [07:28:56 Thread-3] h begin [07:28:58 Thread-3] h end [07:28:58 Thread-3] resume [07:28:58 Thread-1] f [07:28:58 Thread-2] g [07:28:59 Thread-1] f [07:28:59 Thread-2] g [07:29:00 Thread-1] f [07:29:00 Thread-2] g [07:29:01 Thread-1] f [07:29:01 Thread-2] g [07:29:02 Thread-1] f [07:29:02 Thread-2] g [07:29:03 Thread-3] halt
(In response to a question in the comments) This code tries to determine how long it takes for h -thread to get each lock from other worker threads.
It seems that even if h waiting for a lock, another worker thread may, with a rather high probability, release and re-lock the lock. There is no priority for h because he waited longer.
David Bezley introduced thread and GIL issues to PyCon. Here are the pdf slides . This is a fascinating read and can help explain it as well.
import threading import time import logging logger=logging.getLogger(__name__) def f(lock,n): while True: with lock: logger.info(n) time.sleep(1) def h(locks): while True: t=time.time() for n,lock in enumerate(locks): lock.acquire() t2=time.time() logger.info('h acquired {n}: {d}'.format(n=n,d=t2-t)) t=t2 t2=time.time() logger.info('h {d}'.format(d=t2-t)) t=t2 for lock in locks: lock.release() time.sleep(5) logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s %(threadName)s] %(message)s', datefmt='%H:%M:%S') locks=[] N=5 for n in range(N): lock=threading.Lock() locks.append(lock) t=threading.Thread(target=f,args=(lock,n)) t.start() threading.Thread(target=h,args=(locks,)).start()
source share