global scope might be more coherenttoo when passed inall threads reference the same objectbecause they are all part of the same process reallythe process' object memory is shared memory for threadsregardless of how objects in that shared memory are referenced (whether through global scope variablespassed argument namesobject attributesor another wayand while we're at itthe with statement can be used to ensure thread operations around nested block of codemuch like its use to ensure file closure in the prior the thread lock' context manager acquires the lock on with statement entry and releases it on statement exit regardless of exception outcomes the net effect is to save one line of codebut also to guarantee lock release when exceptions are possible example - adds all these coding alternatives to our threaded counter script example - pp \system\threads\thread-count-wait py ""passed in mutex object shared by all threads instead of globalsuse with context manager statement for auto acquire/releasesleep calls added to avoid busy loops and simulate real work ""import _thread as threadtime stdoutmutex thread allocate_lock(numthreads exitmutexes [thread allocate_lock(for in range(numthreads)def counter(myidcountmutex)for in range(count)time sleep( (myid+ )with mutexprint('[% =% (myidi)exitmutexes[myidacquire(shared object passed in diff fractions of second auto acquire/releasewith globalsignal main thread for in range(numthreads)thread start_new_thread(counter( stdoutmutex)while not all(mutex locked(for mutex in exitmutexes)time sleep( print('main thread exiting 'when runthe different sleep times per thread make them run more independentlyc:\pp \system\threadsthread-count-wait py [ = [ = [ = [ = [ = [ = [ = [ = [ = [ = parallel system tools