What are greenlets?¶
Greenlets are lightweight thread-like structures that are scheduled and managed inside the process. They are references to the part of the stack that is used by the thread. Compared to POSIX threads (pthreads), there is no stack allocated up front and there is only as much stack as is actually used by the greenlet
In python, we implement greenlets via the gevent package and we implement pthreads via python’s built-in threading module.
Both green threads (greenlets) and POSIX threads (pthreads) are mechanisms to support multithreaded execution of programs.
POSIX threads use the operating system’s native ability to manage multithreaded processes. When we run pthreads, the kernel schedules and manages the various threads that make up the process.
Green threads emulate multithreaded environments without relying on any native operating system capabilities. Green threads run code in user space that manages and schedules threads.
The key differences between greenlets and pthreads can be summarized as such:
|pthreads can switch between threads pre-emptively, switching control from a running thread to a non-running thread at any time||greenlets only switch when control is explicitly given up by a thread - when using yield() or wait() - or when a thread performs a I/O blocking operation such as read or write|
|On multicore machines, pthreads can run more than one thread. However python’s Global Interpreter Lock (CPython Intepreter) prevents parallelism and concurrency is only effective for I/O-bound programs||greenlets can only run on one single CPU and is useful for I/O-bound programs|
|Race conditions can occur when implementing multi-threading code. Use locks to manage mutex to avoid race conditions.||There’s no possibility of two threads of control accessing the same shared memory at the same time for greenlets so there will not be any race conditions.|
When we install gevent, greenlet as a dependency will be downloaded, compiled (since it is a c extension) and installed.
We can also install greenlet directly:
pip install greenlet Downloading/unpacking greenlet Downloading greenlet-0.4.1.zip (75kB): 75kB downloaded Running setup.py egg_info for package greenlet Installing collected packages: greenlet Running setup.py install for greenlet /usr/bin/clang -fno-strict-aliasing -fno-common -dynamic -pipe -O2 -fwrapv -arch x86_64 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fno-tree-dominator-opts -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c /var/folders/kl/_52jng9s6sl2knv_0jds9w140000gn/T/tmp15ttlr/simple.c -o /var/folders/kl/_52jng9s6sl2knv_0jds9w140000gn/T/tmp15ttlr/var/folders/kl/_52jng9s6sl2knv_0jds9w140000gn/T/tmp15ttlr/simple.o clang: warning: argument unused during compilation: '-fno-tree-dominator-opts' building 'greenlet' extension /usr/bin/clang -fno-strict-aliasing -fno-common -dynamic -pipe -O2 -fwrapv -arch x86_64 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fno-tree-dominator-opts -I/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c greenlet.c -o build/temp.macosx-10.7-x86_64-2.7/greenlet.o clang: warning: argument unused during compilation: '-fno-tree-dominator-opts' In file included from greenlet.c:416: In file included from ./slp_platformselect.h:12: ./platform/switch_amd64_unix.h:40:26: warning: unknown attribute 'noclone' ignored [-Wattributes] __attribute__((noinline, noclone)) int fancy_return_zero(void); ^ ./platform/switch_amd64_unix.h:41:26: warning: unknown attribute 'noclone' ignored [-Wattributes] __attribute__((noinline, noclone)) int ^ 2 warnings generated. /usr/bin/clang -bundle -undefined dynamic_lookup -L/opt/local/lib -L/opt/local/lib/db46 -arch x86_64 build/temp.macosx-10.7-x86_64-2.7/greenlet.o -o build/lib.macosx-10.7-x86_64-2.7/greenlet.so Linking /Users/calvin/.virtualenvs/pyconsg2013/build/greenlet/build/lib.macosx-10.7-x86_64-2.7/greenlet.so to /Users/calvin/.virtualenvs/pyconsg2013/build/greenlet/greenlet.so Successfully installed greenlet Cleaning up...
Notice that the c code gets built and the shared object file greenlet.so is now available for us to import inside our python code.
Here’s a simple example extracted from greenlet docs that explains the nature of greenlet execution:
from greenlet import greenlet def test1(): print 12 gr2.switch() print 34 def test2(): print 56 gr1.switch() print 78 gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()