@@ -1438,59 +1438,88 @@ application).
14381438
14391439.. admonition :: Thread safety
14401440
1441- Most individual operations on :class: `list ` instances are atomic:
1441+ Reading a single element from a :class: `list ` is
1442+ :term: `atomic <atomic operation> `:
14421443
14431444 .. code-block ::
1444- :class: good
1445+ :class: green
1446+
1447+ lst[i] # list.__getitem__
14451448
1446- # The following operations are atomic
1447- lst1 + lst2 # atomic concatenation of two lists
1448- x * lst # atomic repeat of lst x times
1449- item = lst[i] # atomically retrieves item at index i
1450- lst[i] = value # atomically replaces item at index i
1451- lst *= x # atomically extend the list x times
1452-
1453- # Calls to the following list methods are atomic
1454- lst.clear()
1455- lst.copy()
1456- lst.append(item)
1457- lst.insert(idx, item)
1458- lst.pop(idx)
1459- lst.remove(item)
1460- lst.reverse()
1461- lst.sort()
1462-
1463- The following operations/methods are not fully atomic:
1449+ The following methods traverse the list and use :term: `atomic <atomic operation> `
1450+ reads of each item to perform their function. That means that they may
1451+ return results affected by concurrent modifications:
14641452
14651453 .. code-block ::
14661454 :class: maybe
14671455
1456+ item in lst
14681457 lst.index(item)
14691458 lst.count(item)
1470- item in lst
14711459
1472- lst.extend(iterable)
1473- lst += iterable
1460+ All of the above methods/operations are also lock-free. They do not block
1461+ concurrent modifications. Other operations that hold a lock will not block
1462+ these from observing intermediate states.
1463+
1464+ All other operations from here on block using the per-object lock.
1465+
1466+ Writing a single item via ``lst[i] = x `` is safe to call from multiple
1467+ threads and will not corrupt the list.
1468+
1469+ The following operations return new objects and appear
1470+ :term: `atomic <atomic operations> ` to other threads:
1471+
1472+ .. code-block ::
1473+ :class: good
1474+
1475+ lst1 + lst2 # concatenates two lists into a new list
1476+ x * lst # repeats lst x times into a new list
1477+ lst.copy() # returns a shallow copy of the list
1478+
1479+ Methods that only operate on a single elements with no shifting required are
1480+ :term: `atomic <atomic operations> `:
1481+
1482+ .. code-block ::
1483+ :class: good
1484+
1485+ lst.append(x) # append to the end of the list, no shifting required
1486+ lst.pop() # pop element from the end of the list, no shifting required
1487+
1488+ The :meth: `~list.clear ` method is also :term: `atomic <atomic operations> `.
1489+ Other threads cannot observe elements being removed.
1490+
1491+ The :meth: `~list.sort ` method is not :term: `atomic <atomic operation> `.
1492+ Other threads cannot observe intermediate states during sorting, but the
1493+ list appears empty for the duration of the sort.
1494+
1495+ The following operations may allow lock-free operations to observe
1496+ intermediate states since they modify multiple elements in place:
1497+
1498+ .. code-block ::
1499+ :class: maybe
14741500
1475- lst[i:j] = iterable
1501+ lst.insert(idx, item) # shifts elements
1502+ lst.pop(idx) # idx not at the end of the list, shifts elements
1503+ lst *= x # copies elements in place
14761504
1477- The :meth: `~list.index ` and :meth: ` ~list.count ` methods, and the `` in ``
1478- operator, iterate the list without holding a lock. They are safe to call
1479- concurrently but may return results affected by concurrent modifications .
1505+ The :meth: `~list.remove ` method may allow concurrent modifications since
1506+ element comparison may execute arbitrary Python code (via
1507+ :meth: ` ~object.__eq__ `) .
14801508
1481- :meth: `~list.extend ` is safe to call from multiple threads. However, the
1482- operation is fully atomic only when the iterable that's passed to ``extend ``
1483- is a :class: `list `, a :class: `tuple `, a :class: `set `, a :class: `frozenset `,
1484- a :class: `dict ` or a :ref: `dictionary view object <dict-views >` (but not
1485- their subclasses). Otherwise, an iterator is created which can be
1486- concurrently modified by another thread. The same applies to inplace
1487- concatenation of list with other iterables when using ``lst += iterable ``.
1509+ :meth: `~list.extend ` is safe to call from multiple threads. However, its
1510+ guarantees depend on the iterable passed to it. If it is a :class: `list `, a
1511+ :class: `tuple `, a :class: `set `, a :class: `frozenset `, a :class: `dict ` or a
1512+ :ref: `dictionary view object <dict-views >` (but not their subclasses), the
1513+ ``extend `` operation is safe from concurrent modifications to the iterable.
1514+ Otherwise, an iterator is created which can be concurrently modified by
1515+ another thread. The same applies to inplace concatenation of a list with
1516+ other iterables when using ``lst += iterable ``.
14881517
14891518 Similarly, assigning to a list slice with ``lst[i:j] = iterable `` is safe
14901519 to call from multiple threads, but ``iterable `` is only locked when it is
14911520 also a :class: `list ` (but not its subclasses).
14921521
1493- Operations that involve multiple accesses, as well as iteration, are not
1522+ Operations that involve multiple accesses, as well as iteration, are never
14941523 atomic. For example:
14951524
14961525 .. code-block ::
0 commit comments