Python threading (was: Re: global interpreter lock not working as it should)

Bengt Richter bokr at
Sun Aug 4 22:17:20 CEST 2002

On 04 Aug 2002 12:14:10 +0200, martin at (Martin v. Loewis) wrote:

>Jonathan Hogg <jonathan at> writes:
>> I'm sorry, but that's just plain rubbish. If all the threads have the same
>> priority then the thread scheduler will schedule them according to
>> timeslice. I'm really not sure where you get the idea that a thread can only
>> be pre-empted by a higher priority thread. That's just not true.
>I think it is true. The chance that the time slice expires within the
>few instructions when the GIL is released is so low that you'ld
>practically never see a thread switch - yet you do, on many systems.
>The reason for that is that the operating system, in the SCHED_OTHER
>scheduling class, dynamically adjusts priorities of threads - the
>longer a thread runs, the lower its priority gets (down to a lower
>boundary). The other Python threads block on the GIL, and keep their
>priority. Then, when the thread releases the GIL, other threads become
>ready, and have a higher priority - thus immediately causing a thread
>switch (even though the time slice is not expired).
>That, of course, assumes certain details about the OS thread
>scheduler. The OP might be wrong that all operating systems follow
>this strategy, and he is certainly wrong if he assumes that Python
>relies on realtime-threading. But I do believe that such a strategy is
>common across many systems.
>> Yes, please do. I've already posted examples showing four different
>> Operating Systems successfully pre-empting and scheduling CPU-bound Python
>> threads - in most cases thousands of times a second.
>But none of those were using realtime thread facilities, right? I do
>believe that, in the SCHED_FIFO class, you would never observe a
>thread switch in CPU-bound threads. That, of course, would also count
>as "working properly": in SCHED_FIFO, you'd expect applications switch
>threads only when the highest-priority thread blocks.
If there is a mutex behind the GIL implementation, the OS should give ownership
of the mutex to a waiting thread as part of the release operation, so the
same thread could not re-acquire until the new owner executes and releases.
I was guessing this was the way it worked. The dynamic priority adjustment
explanation is interesting, but ISTM an inefficient way to accomplish
"letting another thread run" when voluntarily releasing the GIL for that
apparently immediate purpose (presumably irrespective of remaining time slice).

A mutex should result in a context switch every time there is a release with
a waiter present, since the releaser would reliably fail to re-acquire.
Perhaps that is the way it works on BSD? That might at least partly explain
Jonathan's results.

How multiple waiters are queued would be a separate matter, but presumably
FIFO within priorities. That would depend on the OS's mutex implementation.

ISTM it would be a huge inefficiency, e.g., to make ready a thousand threads
and let them run only to re-block except for one. ISTM that does not match
the semantics of the GIL, and if it is happening, a mutex-like implementation
should be simulated if not directly available. To resolve the question,
I suppose we have to look at what OS mechanisms really are used to implement
the GIL on various platforms.

Bengt Richter

More information about the Python-list mailing list