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

Reply via email to