mwt wrote: > def get_data(self, key): > """Returns a COPY of <key> data element.""" > try: > self.mutex.acquire() > return copy.deepcopy(self.data[key]) > finally: > self.mutex.release()
self.mutex.acquire() should be outside the try block, like this: self.mutex.acquire() try: return copy.deepcopy(self.data[key]) finally: self.mutex.release() The reason is: what if the call to self.mutex.acquire fails (raises an exception)? Suppose that another thread (#1) has the mutex, and this thread (#2) is waiting on it, when an exception is raised in it (say a timeout, keyboard interrupt, or runtime error). What will happen? Because the acquire call is inside the try block, the finally block gets run, and thread #2 releases the mutex being held by #1. But wait! Now let's say there's a third thread (#3) that's also waiting on this mutex. When #2 releases the mutex, #3 runs. But #1 is not done... #3 corrupts the data. You've just destroyed the secret plans. You're fired. The same logic applies to open/close, allocate/deallocate, set/unset, or any other resource acquisistion. Acquire the resource before the try block, release it in the finally block. (Note: it may be the case that 1. the acquisition function cannot raise an exception for some reason, or 2. attempting to release a unacquired resource is harmless, in which case it won't exactly hurt to put the acquisition inside the try block. It might be true of mutexes for all I know. But even in those rare cases, I recommend always sticking to the idiom for consistency.) Carl Banks -- http://mail.python.org/mailman/listinfo/python-list