From the course: Python Parallel and Concurrent Programming Part 1

Global interpreter lock: Python demo - Python Tutorial

From the course: Python Parallel and Concurrent Programming Part 1

Start my 1-month free trial

Global interpreter lock: Python demo

- [Instructor] Using threads to handle concurrent tasks in Python is fairly straightforward. However, the Python interpreter will not allow those concurrent threads to execute simultaneously and parallel, due to a mechanism called the global interpreter lock, or GIL. It's something that's unique to Python and important to address up front. The GIL is a mechanism in Python that prevents multiple Python threads from executing at the same time. That means if your program is written to have 10 concurrent threads, only one of them can execute at a time while the other nine wait their turn. This may seem like an odd limitation, but remember that under the hood, your Python program is actually being executed by a program called an interpreter. The interpreter compiles your Python program into an intermediate bytecode which is then executed with a virtual machine along with any necessary modules from the library. The default and by far most widely used interpreter is CPython, and as its name suggests, its underlying code is written in a mix of C and Python. The global interpreter lock was implemented as a simple way to provide thread-safe memory management in CPython by only letting one Python thread execute at a time. There have been several proposals to eliminate the GIL from CPython because of its negative impact on parallel performance, but in most cases, the advantages of having the GIL outweigh its disadvantages. There are other implementations of Python that do not have the GIL including Jython, which is Java based, IronPython, which is .NET based, and PyPy-STM. But CPython is the default and most popular interpreter so the GIL lives on as a contentious element of Python. Now just because CPython has the GIL does not mean there's no value in writing multi-threaded Python programs. Many applications are I/O-bound, meaning they're mostly waiting on external actions, like network operations or user input. For those types of I/O-intensive tasks, the GIL does not create a significant bottleneck and you can gain a lot by using Python's threading module to implement multiple concurrent threads. On the other hand, if your application is CPU bound and spends most of its time performing CPU-intensive computations, then the GIL can negatively impact multi-threaded performance, but there are ways to get around it. Because Python is an interpreted language, it's inherently slow, so processor-heavy algorithms are often written using faster compiled languages like C++. And then included in function libraries that a top-level Python program can call into. Those operations can then execute outside of the GIL's restrictions using parallel threads. If you want to keep everything written in Python, the workaround is to use Python's multiprocessing package to implement your program with multiple processes instead of multiple threads. Each Python process will be its own instance of the Python interpreter with its own GIL, so the separate processes can execute in parallel. The downside here is that communication between processes is a bit more complicated than between threads, and creating multiple processes uses more system resources than creating multiple threads. For most of the Python examples in this course, we'll stick with using the threading module to demonstrate the programming concepts with concurrent threads. As you'll see, even with the GIL restricting execution, multi-threaded Python programs can still run into a variety of problems that you'll need to protect against. The GIL does not exist to keep you safe. When we reach examples later in this course that involve more CPU-intensive tasks, we'll switch over to using the multiprocessing package so you can see how to use that, as well.

Contents