Думайте об этом так:
На однопроцессорном компьютере многопоточность выполняется путем приостановки одного потока и запуска другого достаточно быстро, чтобы казалось, что он работает одновременно. Это похоже на Python с GIL: на самом деле работает только один поток.
Проблема в том, что поток может быть приостановлен где угодно, например, если я хочу вычислить b = (a + b) * 3, это может привести к инструкциям примерно так:
1 a += b
2 a *= 3
3 b = a
Теперь предположим, что он работает в потоке, и этот поток приостанавливается после строки 1 или 2, а затем запускается и запускается другой поток:
b = 5
Затем, когда другой поток возобновляет работу, b перезаписывается старыми вычисленными значениями, что, вероятно, не то, что ожидалось.
Таким образом, вы можете видеть, что, хотя они и не работают одновременно, вам все равно нужна блокировка.