The Py_BEGIN_ALLOW_THREADS pattern you're implementing is literally how NumPy releases the GIL during heavy array computation so other Python threads can run, and it's the exact lock PEP 703 (Sam Gross's free-threaded CPython, shipped experimentally in 3.13) proposes removing. Understanding when the GIL is held is the difference between threading code that helps and threading code that silently does nothing for CPU-bound work.