2006/1/26, Mike Looijmans <[EMAIL PROTECTED]>: > Two comments: > 1. (bug): The acquire() call should be *outside* the try ... finally > block. You do not want to release a lock that you did not aquire. > > 2. (optimization): If you are not planning to change the path, you do > not have to aquire the lock. Aquiring a lock is quite expensive, so the > double-check will have much less impact on performance. > > > if config.has_key("PythonPath"): > pathstring = config["PythonPath"] > if not _path_cache.has_key(pathstring): > # acquire must be done outside the try block > _path_cache_lock.acquire() > try: > # double-check, because two threads might come > # to the same conclusion up until here. > if not _path_cache.has_key(pathstring): > newpath = eval(pathstring) > _path_cache[pathstring] = None > sys.path[:] = newpath > finally: > _path_cache_lock.release() > > > > Mike Looijmans > Philips Natlab / Topic Automation
Hi, Your optimisation is called "double-checked locking", and it is now known to be broken, especially on multiple-CPU systems. The problem exists in numerous languages. Here is an explanation of the problem : http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html Now, maybe Python is not touched by this problem due to its relatively poor support for multithreading. The presence of the GIL guarantees that only one thread of Python bytecode interpreter runs at a time, but still, in a multiple CPU environment, you can get bitten by local caching issues. As this thing is a bit hairy, I think we should first strive for correctness, then care about performance later. And no, I won't bother you with one more quote about premature this and the root of that ;). Regards, Nicolas