If you want your application to perform several tasks at once, you can use threads. Python can handle threads, but many developers find thread programming to be very tricky. Threads let you set up a series of processes (or sub-processes) each of which can be run independently, but which can be brought back together later and/or co-ordinated as they run. For many applications, threads are overkill but on some occasions they can be useful.
Before we begin to look at the code that makes threading work, the most important feature we must look at is Python's global interpreter lock. If two or more threads were to attempt to manipulate the same object at the same time, problems would inevitably pop up. The global interpreter lock fixes this. Only one thread can perform an action at any given time. Python automatically switches between threads when it is needed.
In order to support multi threaded Python programs the interpreter regularly releases and reacquires the lock, by default every 10 bytecode instructions. This can however be changed using the sys.setcheckinterval() function. The lock is also released and reacquired around potentially blocking I/O operations like reading or writing a file, so that other threads can run while the thread that requests the I/O is waiting for the I/O operation to complete.
The Python Interpreter keeps some book keeping info per thread, for which it uses a data structure called PyThreadState. Earlier the state was stored in global variables and switching threads could cause problems. In particular, exception handling is now thread safe when the application uses sys.exc_info() to access the exception last raised in the current thread. There's one global variable left, however: the pointer to the current PyThreadState structure. While most thread packages have a way to store ``per-thread global data,'' Python's internal platform independent thread abstraction doesn't support this yet. Therefore, the current thread state must be manipulated explicitly.
The global interpreter lock is used to protect the pointer to the current thread state. When releasing the lock and saving the thread state, the current thread state pointer must be retrieved before the lock is released (since another thread could immediately acquire the lock and store its own thread state in the global variable). Conversely, when acquiring the lock and restoring the thread state, the lock must be acquired before storing the thread state pointer
Bookmarks