@@ -5510,6 +5510,12 @@ can be used interchangeably to index the same dictionary entry.
55105510
55115511.. admonition :: Thread safety
55125512
5513+ Creating a dictionary with the :class: `dict ` constructor is atomic when the
5514+ argument to it is a :class: `dict ` or a :class: `tuple `. When using the
5515+ :meth: `dict.fromkeys ` method, dictionary creation is atomic when the
5516+ argument is a :class: `dict `, :class: `tuple `, :class: `set ` or
5517+ :class: `frozenset `.
5518+
55135519 The following operations and function are lock-free and
55145520 :term: `atomic <atomic operation> `.
55155521
@@ -5606,14 +5612,39 @@ can be used interchangeably to index the same dictionary entry.
56065612 # NOT atomic: read-modify-write
56075613 d[key] = d[key] + 1
56085614
5609- # NOT atomic: check-then-act
5615+ # NOT atomic: check-then-act (TOCTOU)
56105616 if key in d:
56115617 del d[key]
56125618
56135619 # NOT thread-safe: iteration while modifying
5614- for key in d:
5620+ for key, value in d.items() :
56155621 process(key) # another thread may modify d
56165622
5623+ To avoid time-of-check to time-of-use (TOCTOU) issues, use atomic
5624+ operations or handle exceptions:
5625+
5626+ .. code-block ::
5627+ :class: good
5628+
5629+ # Use pop() with default instead of check-then-delete
5630+ d.pop(key, None)
5631+
5632+ # Or handle the exception
5633+ try:
5634+ del d[key]
5635+ except KeyError:
5636+ pass
5637+
5638+ To safely iterate over a dictionary that may be modified by another
5639+ thread, iterate over a copy:
5640+
5641+ .. code-block ::
5642+ :class: good
5643+
5644+ # Make a copy to iterate safely
5645+ for key, value in d.copy().items():
5646+ process(key)
5647+
56175648 Consider external synchronization when sharing :class: `dict ` instances
56185649 across threads. See :ref: `freethreading-python-howto ` for more information.
56195650
0 commit comments