Issue #9260: A finer-grained import lock.

Most of the import sequence now uses per-module locks rather than the
global import lock, eliminating well-known issues with threads and imports.
This commit is contained in:
Antoine Pitrou 2012-05-17 18:55:59 +02:00
parent 5cec9d2ae5
commit ea3eb88bca
12 changed files with 3777 additions and 3041 deletions

View file

@ -30,13 +30,13 @@ Importing Modules
.. c:function:: PyObject* PyImport_ImportModuleNoBlock(const char *name)
This version of :c:func:`PyImport_ImportModule` does not block. It's intended
to be used in C functions that import other modules to execute a function.
The import may block if another thread holds the import lock. The function
:c:func:`PyImport_ImportModuleNoBlock` never blocks. It first tries to fetch
the module from sys.modules and falls back to :c:func:`PyImport_ImportModule`
unless the lock is held, in which case the function will raise an
:exc:`ImportError`.
This function is a deprecated alias of :c:func:`PyImport_ImportModule`.
.. versionchanged:: 3.3
This function used to fail immediately when the import lock was held
by another thread. In Python 3.3 though, the locking scheme switched
to per-module locks for most purposes, so this function's special
behaviour isn't needed anymore.
.. c:function:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist)

View file

@ -112,18 +112,29 @@ This module provides an interface to the mechanisms used to implement the
Return ``True`` if the import lock is currently held, else ``False``. On
platforms without threads, always return ``False``.
On platforms with threads, a thread executing an import holds an internal lock
until the import is complete. This lock blocks other threads from doing an
import until the original import completes, which in turn prevents other threads
from seeing incomplete module objects constructed by the original thread while
in the process of completing its import (and the imports, if any, triggered by
that).
On platforms with threads, a thread executing an import first holds a
global import lock, then sets up a per-module lock for the rest of the
import. This blocks other threads from importing the same module until
the original import completes, preventing other threads from seeing
incomplete module objects constructed by the original thread. An
exception is made for circular imports, which by construction have to
expose an incomplete module object at some point.
.. note::
Locking semantics of imports are an implementation detail which may
vary from release to release. However, Python ensures that circular
imports work without any deadlocks.
.. versionchanged:: 3.3
In Python 3.3, the locking scheme has changed to per-module locks for
the most part.
.. function:: acquire_lock()
Acquire the interpreter's import lock for the current thread. This lock should
be used by import hooks to ensure thread-safety when importing modules.
Acquire the interpreter's global import lock for the current thread.
This lock should be used by import hooks to ensure thread-safety when
importing modules.
Once a thread has acquired the import lock, the same thread may acquire it
again without blocking; the thread must release it once for each time it has
@ -134,8 +145,8 @@ This module provides an interface to the mechanisms used to implement the
.. function:: release_lock()
Release the interpreter's import lock. On platforms without threads, this
function does nothing.
Release the interpreter's global import lock. On platforms without
threads, this function does nothing.
.. function:: reload(module)