Skip to content

Commit 858b7bf

Browse files
committed
gh-142518: Document thread-safety guarantees of bytearray objects
1 parent 80b2b88 commit 858b7bf

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

Doc/library/stdtypes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,6 +3472,11 @@ The representation of bytearray objects uses the bytes literal format
34723472
``bytearray([46, 46, 46])``. You can always convert a bytearray object into
34733473
a list of integers using ``list(b)``.
34743474

3475+
.. seealso::
3476+
3477+
For detailed information on thread-safety guarantees for :class:`bytearray`
3478+
objects, see :ref:`thread-safety-bytearray`.
3479+
34753480

34763481
.. _bytes-methods:
34773482

Doc/library/threadsafety.rst

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,104 @@ thread, iterate over a copy:
260260
261261
Consider external synchronization when sharing :class:`dict` instances
262262
across threads.
263+
264+
265+
.. _thread-safety-bytearray:
266+
267+
Thread safety for bytearray objects
268+
===================================
269+
270+
The :func:`len` function is lock-free and :term:`atomic <atomic operation>`.
271+
272+
Concatenation and comparisons use the buffer protocol, which prevents
273+
resizing but does not hold the per-object lock. These operations may
274+
observe intermediate states from concurrent modifications:
275+
276+
.. code-block::
277+
:class: maybe
278+
279+
ba + other # may observe concurrent writes
280+
ba == other # may observe concurrent writes
281+
ba < other # may observe concurrent writes
282+
283+
All other operations from here on hold the per-object lock.
284+
285+
Reading a single element or slice is safe to call from multiple threads:
286+
287+
.. code-block::
288+
:class: good
289+
290+
ba[i] # bytearray.__getitem__
291+
ba[i:j] # slice
292+
293+
The following operations are safe to call from multiple threads and will
294+
not corrupt the bytearray:
295+
296+
.. code-block::
297+
:class: good
298+
299+
ba[i] = x # write single byte
300+
ba[i:j] = values # write slice
301+
ba.append(x) # append single byte
302+
ba.extend(other) # extend with iterable
303+
ba.insert(i, x) # insert single byte
304+
ba.pop() # remove and return last byte
305+
ba.pop(i) # remove and return byte at index
306+
ba.remove(x) # remove first occurrence
307+
ba.reverse() # reverse in place
308+
ba.clear() # remove all bytes
309+
310+
Slice assignment locks both objects when *values* is a :class:`bytearray`:
311+
312+
.. code-block::
313+
:class: good
314+
315+
ba[i:j] = other_bytearray # both locked
316+
317+
The following operations return new objects and hold the per-object lock
318+
for the duration:
319+
320+
.. code-block::
321+
:class: good
322+
323+
ba.copy() # returns a shallow copy
324+
ba * n # repeat into new bytearray
325+
326+
The membership test holds the lock for its duration:
327+
328+
.. code-block::
329+
:class: good
330+
331+
x in ba # bytearray.__contains__
332+
333+
All other bytearray methods (such as :meth:`~bytearray.find`,
334+
:meth:`~bytearray.replace`, :meth:`~bytearray.split`,
335+
:meth:`~bytearray.decode`, etc.) hold the per-object lock for their
336+
duration.
337+
338+
Operations that involve multiple accesses, as well as iteration, are never
339+
atomic:
340+
341+
.. code-block::
342+
:class: bad
343+
344+
# NOT atomic: check-then-act
345+
if x in ba:
346+
ba.remove(x)
347+
348+
# NOT thread-safe: iteration while modifying
349+
for byte in ba:
350+
process(byte) # another thread may modify ba
351+
352+
To safely iterate over a bytearray that may be modified by another
353+
thread, iterate over a copy:
354+
355+
.. code-block::
356+
:class: good
357+
358+
# Make a copy to iterate safely
359+
for byte in ba.copy():
360+
process(byte)
361+
362+
Consider external synchronization when sharing :class:`bytearray` instances
363+
across threads. See :ref:`freethreading-python-howto` for more information.

0 commit comments

Comments
 (0)