On Oct 21, 1:12*am, Piotr Sobolewski <piotr_sobolew. ..@o2.plwrote:
Hello,
I have such program:
import time
import thread
def f():
* * global lock
* * while True:
* * * * lock.acquire()
* * * * print thread.get_iden t()
* * * * time.sleep(1)
* * * * lock.release()
lock=thread.all ocate_lock()
thread.start_ne w_thread(f,())
thread.start_ne w_thread(f,())
time.sleep(60)
Let me state first of all that you are going about it all wrong.
Simple locks don't handle the above siutation very well because,
frankly, there's no benefit to using threads in this way at all.
Since neither thread can run at the same time as the other, you might
as well have just used ordinary looping.
Normally, when using threads, you only want to use locking for brief
periods when accessing data shared between threads, like so:
def f():
do_some_stuff
lock.acquire()
access_shared_d ata
lock.release()
do_some_more_st uff
Starvation is much less likely to occur in this situation. (The
interpreter periodically releases the GIL, so if there's stuff between
a release and the next acquire, it'll have a window in which to
release the GIL--unlike in your example where the window was very
tiny.)
As you can see, I start two threads. Each one works in an infinite
loop.
Inside that loop it acquires lock, prints its own id, sleeps a bit and
then
releases lock.
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 - after it releases the lock, it almost immediately
(in
the very next bytecode command) reacquires it.
Not really the GIL's fault. Or rather, fiddling with the GIL is the
wrong way to get what you want here.
What you want is some kind of thread balancing, to make sure all
threads have a chance to run. Let me stress that, in this case, you
only need balancing because you're using threads incorrectly. But
I'll mention one way to do it anyway.
The easiest way I can think of is to use a counter that is protected
by a threading.Condi tion. One thread only runs when the counter is
even, the other only when it's odd. It might be implemented like
this:
counter = 0
c = threading.Condi tion()
def f():
global counter
c.acquire()
while counter % 1 == 0: # == 1 for the other thread
c.wait()
do_something()
counter += 1
c.notify()
c.release()
The reason threading.Condi tion is required and not a simple lock is
that simply acquiring the lock is not enough; the counter must be in
the right state as well.
Carl Banks