https://github.com/python/cpython/commit/12dbae4c02dac197330d5bfa650b495e962aba6d
commit: 12dbae4c02dac197330d5bfa650b495e962aba6d
branch: main
author: Lysandros Nikolaou <[email protected]>
committer: lysnikolaou <[email protected]>
date: 2026-02-11T13:55:36+01:00
summary:

gh-142518: Define lock-free and per-object lock (#144548)

- Add definitions of lock-free and per-object lock to the glossary
- Cross-reference these from list thread safety notes
- Change admonition to rubric

files:
M Doc/glossary.rst
M Doc/library/stdtypes.rst

diff --git a/Doc/glossary.rst b/Doc/glossary.rst
index 24b95b88dfb651..1dccb77cc53228 100644
--- a/Doc/glossary.rst
+++ b/Doc/glossary.rst
@@ -951,6 +951,16 @@ Glossary
       to locks exist such as queues, producer/consumer patterns, and
       thread-local state. See also :term:`deadlock`, and :term:`reentrant`.
 
+   lock-free
+      An operation that does not acquire any :term:`lock` and uses atomic CPU
+      instructions to ensure correctness. Lock-free operations can execute
+      concurrently without blocking each other and cannot be blocked by
+      operations that hold locks. In :term:`free-threaded <free threading>`
+      Python, built-in types like :class:`dict` and :class:`list` provide
+      lock-free read operations, which means other threads may observe
+      intermediate states during multi-step modifications even when those
+      modifications hold the :term:`per-object lock`.
+
    loader
       An object that loads a module.
       It must define the :meth:`!exec_module` and :meth:`!create_module` 
methods
@@ -1217,6 +1227,16 @@ Glossary
       <faq-argument-vs-parameter>`, the :class:`inspect.Parameter` class, the
       :ref:`function` section, and :pep:`362`.
 
+   per-object lock
+      A :term:`lock` associated with an individual object instance rather than
+      a global lock shared across all objects. In :term:`free-threaded
+      <free threading>` Python, built-in types like :class:`dict` and
+      :class:`list` use per-object locks to allow concurrent operations on
+      different objects while serializing operations on the same object.
+      Operations that hold the per-object lock prevent other locking operations
+      on the same object from proceeding, but do not block :term:`lock-free`
+      operations.
+
    path entry
       A single location on the :term:`import path` which the :term:`path
       based finder` consults to find modules for importing.
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
index c8dc834fe84446..3745f32d874bd4 100644
--- a/Doc/library/stdtypes.rst
+++ b/Doc/library/stdtypes.rst
@@ -1441,108 +1441,111 @@ application).
          list appear empty for the duration, and raises :exc:`ValueError` if 
it can
          detect that the list has been mutated during a sort.
 
-.. admonition:: Thread safety
+.. _thread-safety-list:
 
-   Reading a single element from a :class:`list` is
-   :term:`atomic <atomic operation>`:
+.. rubric:: Thread safety for list objects
 
-   .. code-block::
-      :class: green
+Reading a single element from a :class:`list` is
+:term:`atomic <atomic operation>`:
 
-      lst[i]   # list.__getitem__
+.. code-block::
+   :class: green
 
-   The following methods traverse the list and use :term:`atomic <atomic 
operation>`
-   reads of each item to perform their function. That means that they may
-   return results affected by concurrent modifications:
+   lst[i]   # list.__getitem__
 
-   .. code-block::
-      :class: maybe
+The following methods traverse the list and use :term:`atomic <atomic 
operation>`
+reads of each item to perform their function. That means that they may
+return results affected by concurrent modifications:
 
-      item in lst
-      lst.index(item)
-      lst.count(item)
+.. code-block::
+   :class: maybe
 
-   All of the above methods/operations are also lock-free. They do not block
-   concurrent modifications. Other operations that hold a lock will not block
-   these from observing intermediate states.
+   item in lst
+   lst.index(item)
+   lst.count(item)
 
-   All other operations from here on block using the per-object lock.
+All of the above operations avoid acquiring :term:`per-object locks
+<per-object lock>`. They do not block concurrent modifications. Other
+operations that hold a lock will not block these from observing intermediate
+states.
 
-   Writing a single item via ``lst[i] = x`` is safe to call from multiple
-   threads and will not corrupt the list.
+All other operations from here on block using the :term:`per-object lock`.
 
-   The following operations return new objects and appear
-   :term:`atomic <atomic operation>` to other threads:
+Writing a single item via ``lst[i] = x`` is safe to call from multiple
+threads and will not corrupt the list.
 
-   .. code-block::
-      :class: good
+The following operations return new objects and appear
+:term:`atomic <atomic operation>` to other threads:
 
-      lst1 + lst2    # concatenates two lists into a new list
-      x * lst        # repeats lst x times into a new list
-      lst.copy()     # returns a shallow copy of the list
+.. code-block::
+   :class: good
 
-   Methods that only operate on a single elements with no shifting required are
-   :term:`atomic <atomic operation>`:
+   lst1 + lst2    # concatenates two lists into a new list
+   x * lst        # repeats lst x times into a new list
+   lst.copy()     # returns a shallow copy of the list
 
-   .. code-block::
-      :class: good
+The following methods that only operate on a single element with no shifting
+required are :term:`atomic <atomic operation>`:
 
-      lst.append(x)  # append to the end of the list, no shifting required
-      lst.pop()      # pop element from the end of the list, no shifting 
required
+.. code-block::
+   :class: good
 
-   The :meth:`~list.clear` method is also :term:`atomic <atomic operation>`.
-   Other threads cannot observe elements being removed.
+   lst.append(x)  # append to the end of the list, no shifting required
+   lst.pop()      # pop element from the end of the list, no shifting required
 
-   The :meth:`~list.sort` method is not :term:`atomic <atomic operation>`.
-   Other threads cannot observe intermediate states during sorting, but the
-   list appears empty for the duration of the sort.
+The :meth:`~list.clear` method is also :term:`atomic <atomic operation>`.
+Other threads cannot observe elements being removed.
 
-   The following operations may allow lock-free operations to observe
-   intermediate states since they modify multiple elements in place:
+The :meth:`~list.sort` method is not :term:`atomic <atomic operation>`.
+Other threads cannot observe intermediate states during sorting, but the
+list appears empty for the duration of the sort.
 
-   .. code-block::
-      :class: maybe
+The following operations may allow :term:`lock-free` operations to observe
+intermediate states since they modify multiple elements in place:
 
-      lst.insert(idx, item)  # shifts elements
-      lst.pop(idx)           # idx not at the end of the list, shifts elements
-      lst *= x               # copies elements in place
+.. code-block::
+   :class: maybe
 
-   The :meth:`~list.remove` method may allow concurrent modifications since
-   element comparison may execute arbitrary Python code (via
-   :meth:`~object.__eq__`).
+   lst.insert(idx, item)  # shifts elements
+   lst.pop(idx)           # idx not at the end of the list, shifts elements
+   lst *= x               # copies elements in place
 
-   :meth:`~list.extend` is safe to call from multiple threads.  However, its
-   guarantees depend on the iterable passed to it. If it is a :class:`list`, a
-   :class:`tuple`, a :class:`set`, a :class:`frozenset`, a :class:`dict` or a
-   :ref:`dictionary view object <dict-views>` (but not their subclasses), the
-   ``extend`` operation is safe from concurrent modifications to the iterable.
-   Otherwise, an iterator is created which can be concurrently modified by
-   another thread.  The same applies to inplace concatenation of a list with
-   other iterables when using ``lst += iterable``.
+The :meth:`~list.remove` method may allow concurrent modifications since
+element comparison may execute arbitrary Python code (via
+:meth:`~object.__eq__`).
 
-   Similarly, assigning to a list slice with ``lst[i:j] = iterable`` is safe
-   to call from multiple threads, but ``iterable`` is only locked when it is
-   also a :class:`list` (but not its subclasses).
+:meth:`~list.extend` is safe to call from multiple threads.  However, its
+guarantees depend on the iterable passed to it. If it is a :class:`list`, a
+:class:`tuple`, a :class:`set`, a :class:`frozenset`, a :class:`dict` or a
+:ref:`dictionary view object <dict-views>` (but not their subclasses), the
+``extend`` operation is safe from concurrent modifications to the iterable.
+Otherwise, an iterator is created which can be concurrently modified by
+another thread.  The same applies to inplace concatenation of a list with
+other iterables when using ``lst += iterable``.
 
-   Operations that involve multiple accesses, as well as iteration, are never
-   atomic. For example:
+Similarly, assigning to a list slice with ``lst[i:j] = iterable`` is safe
+to call from multiple threads, but ``iterable`` is only locked when it is
+also a :class:`list` (but not its subclasses).
 
-   .. code-block::
-      :class: bad
+Operations that involve multiple accesses, as well as iteration, are never
+atomic. For example:
 
-      # NOT atomic: read-modify-write
-      lst[i] = lst[i] + 1
+.. code-block::
+   :class: bad
 
-      # NOT atomic: check-then-act
-      if lst:
-          item = lst.pop()
+   # NOT atomic: read-modify-write
+   lst[i] = lst[i] + 1
 
-      # NOT thread-safe: iteration while modifying
-      for item in lst:
-          process(item)  # another thread may modify lst
+   # NOT atomic: check-then-act
+   if lst:
+         item = lst.pop()
 
-   Consider external synchronization when sharing :class:`list` instances
-   across threads.  See :ref:`freethreading-python-howto` for more information.
+   # NOT thread-safe: iteration while modifying
+   for item in lst:
+         process(item)  # another thread may modify lst
+
+Consider external synchronization when sharing :class:`list` instances
+across threads.  See :ref:`freethreading-python-howto` for more information.
 
 
 .. _typesseq-tuple:

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to