> When I run it, I notice that only one thread works and the other one > never has a chance to run. I guess it is because the thread don't > have a chance to release the GIL
This guess is wrong. A call to lock.acquire *does* release the GIL, (as does the call to thread.sleep, as somebody else pointed out). The real problem is that thread.lock is not guaranteed to be fair (and isn't fair on most operating systems). What happens is this (slight variations possible) thread 1 thread 2 acquire GIL (wait for GIL) release GIL (OS might schedule thread 2 here, but typically won't) acquire lock acquire GIL print ident release GIL sleep acquire GIL release GIL (wait for lock) (still hold by thread 1) (wait for GIL) acquire GIL release lock release GIL (wait for lock) (both threads waiting for lock here. OS choses thread 1) acquire lock acquire GIL (and so on) To make that work the way you want it, you need a fair wake-up order. Here is an example, using a list of Event objects: import time import threading events = [] def f(e): while True: events.append(e) token = e.wait() e.clear() print threading.currentThread() time.sleep(1) events.remove(e) events[0].set() for i in range(3): t = threading.Thread(target=f, args=(threading.Event(),)) t.setDaemon(1) t.start() while not events: print events time.sleep(0.1) events[0].set() time.sleep(10) HTH, Martin -- http://mail.python.org/mailman/listinfo/python-list