In Part 1 we looked inside Python threads. We saw why threads help when the program is waiting, why they struggle when the program is computing, and why the GIL matters. In Part 2 we connected those ...