Threading in Python
Threads can speed up code that is largely IO-bounded, not CPU-bounded.
The GIL is the Global Interpreter Lock. It ensures that threads get a slice of CPU time to execute by pausing a thread and starting another.
Locks prevent the GIL from interrupting short spans of code. This is helpful if you have multiple threads that can change the value of shared data. In many cases, changing the value of data can reduce down to multiple bytecode operations. Some operations are atomic, like the functions sort, which means they only reduce down to one byte code.
In general, for any shared data between threads that can change that data, wrap the section of code that changes the data in a lock unless that code is atomic.