Why the Global Interpreter Lock?

In general, for any thread safety problem you will need to protect your internal data structures with locks.
This can be done with various levels of granularity.

  • You can use fine-grained locking, where every separate structure has its own lock.

  • You can use coarse-grained locking where one lock protects everything (the GIL approach).

There are various pros and cons of each method. Fine-grained locking allows greater parallelism – two threads can
execute in parallel when they don’t share any resources. However there is a much larger administrative overhead. For
every line of code, you may need to acquire and release several locks.

The coarse grained approach is the opposite. Two threads can’t run at the same time, but an individual thread will run faster because its not doing so much bookkeeping. Ultimately it comes down to a tradeoff between single-threaded speed and parallelism.

There have been a few attempts to remove the GIL in python, but the extra overhead for single threaded machines was generally too large. Some cases can actually be slower even on multi-processor machines
due to lock contention.

Do other languages that are compiled to bytecode employ a similar mechanism?

It varies, and it probably shouldn’t be considered a language property so much as an implementation property.
For instance, there are Python implementations such as Jython and IronPython which use the threading approach of their underlying VM, rather than a GIL approach. Additionally, the next version of Ruby looks to be moving towards introducing a GIL.

Leave a Comment