You can use a Semaphore for your purposes
A semaphore manages an internal counter which is decremented by each acquire() call and incremented by each release() call. The counter can never go below zero; when acquire() finds that it is zero, it blocks, waiting until some other thread calls release().
A default value of Semaphore is 1,
class threading.Semaphore(value=1)
so only one thread would be active at once:
import queue import threading import time fifo_queue = queue.Queue() semaphore = threading.Semaphore() def hd(): with semaphore: print("hi") time.sleep(1) print("done") for i in range(3): cc = threading.Thread(target=hd) fifo_queue.put(cc) cc.start()
hi done hi done hi done
As @user2357112supportsMonica mentioned in comments RLock would be more safe option
class threading.RLock
This class implements reentrant lock objects. A reentrant lock must be released by the thread that acquired it. Once a thread has acquired a reentrant lock, the same thread may acquire it again without blocking; the thread must release it once for each time it has acquired it.
import queue import threading import time fifo_queue = queue.Queue() lock = threading.RLock() def hd(): with lock: print("hi") time.sleep(1) print("done") for i in range(3): cc = threading.Thread(target=hd) fifo_queue.put(cc) cc.start()