My understanding is that threading allows in reality to have only one thread active at a time, continously switching between threads. This is useful when having IO-bound operations where the worload is effectively offloaded somewhere else (an PI, a database, ...).
If so, why is there a need for a Lock() object? There is no risk that a variable is accessed by two threads simultaneously (as it can be the case in multiprocessing) so I fail to see a real usage for locks in this context.
First of all, locks secure whole areas, think of updating a file:
with lock: with open("some_file", "r+") as f: do_something(f)
Even single operations like
a['b'] += 1
might lead to multiple operations (read value of
a['b'], increment, write to
a['b']), and need to be secured by a lock:
with lock: a['b'] += 1