I've come accross functionality which required the following pattern:
from threading import Lock
the_list = 
the_list_lock = Lock()
the_list = HidingLock()
with the_list as l:
I think the reason there's nothing in the standard library is because for it to be there it would need to make cast iron access guarantees. To provide anything less would give a false sense of security that could lead to just as many concurrency issues.
It's also nearly impossible to make these guarantees, without making substantial performance sacrifices. As such, it is left up to the user to consider how they will manage concurrency issues. This is in line with one of Python's the philosophies of "we're all consenting adults". That is, if you're writing a class I think it's reasonable that you should know which attributes you need to acquire a lock before accessing the attribute. Or, if you're really that concerned, write a wrapper/proxy class that controls all access to the underlying object.
With your example there are a number of ways in which the target object could accidentally escape. If the programmer isn't paying enough attention to the code they're writing/maintaining, then this
HiddenLock could provide that false sense of security. For instance:
with the_lock as obj: pass obj.func() # erroneous with the_lock as obj: return obj.func() # possibly erroneous # What if the return value of `func' contains a self reference? with the_lock as obj: obj_copy = obj[:] obj_copy = 2 # erroneous?
This last one is particularly pernicious. Whether this code is thread safe depends not on the code within the with block, or even the code after the block. Instead, it is the implementation of the class of
obj that will mean this code is thread safe or not. For instance, if
obj is a
list then this is safe as
obj[:] creates a copy. However, if
obj is a
obj[:] creates a view and so the operation is unsafe.
Actually, if the contents of
obj were mutable then this could be unsafe as regardless (eg.