@@ -548,3 +548,59 @@ Thread safety for bytearray objects
548548
549549 Consider external synchronization when sharing :class: `bytearray ` instances
550550 across threads. See :ref: `freethreading-python-howto ` for more information.
551+
552+
553+ .. _thread-safety-memoryview :
554+
555+ Thread safety for memoryview objects
556+ ====================================
557+
558+ :class: `memoryview ` objects provide access to the internal data of an
559+ underlying object without copying. Thread safety depends on both the
560+ memoryview itself and the underlying buffer exporter.
561+
562+ The memoryview implementation uses atomic operations to track its own
563+ exports in the :term: `free-threaded build `. Creating and
564+ releasing a memoryview are thread-safe. Attribute access (e.g.,
565+ :attr: `~memoryview.shape `, :attr: `~memoryview.format `) reads fields that
566+ are immutable for the lifetime of the memoryview, so concurrent reads
567+ are safe as long as the memoryview has not been released.
568+
569+ However, the actual data accessed through the memoryview is owned by the
570+ underlying object. Concurrent access to this data is only safe if the
571+ underlying object supports it:
572+
573+ * For immutable objects like :class: `bytes `, concurrent reads through
574+ multiple memoryviews are safe.
575+
576+ * For mutable objects like :class: `bytearray `, reading and writing the
577+ same memory region from multiple threads without external
578+ synchronization is not safe and may result in data corruption.
579+ Note that even read-only memoryviews of mutable objects do not
580+ prevent data races if the underlying object is modified from
581+ another thread.
582+
583+ .. code-block ::
584+ :class: bad
585+
586+ # NOT safe: concurrent writes to the same buffer
587+ data = bytearray(1000)
588+ view = memoryview(data)
589+ # Thread 1: view[0:500] = b'x' * 500
590+ # Thread 2: view[0:500] = b'y' * 500
591+
592+ .. code-block ::
593+ :class: good
594+
595+ # Safe: use a lock for concurrent access
596+ import threading
597+ lock = threading.Lock()
598+ data = bytearray(1000)
599+ view = memoryview(data)
600+
601+ with lock:
602+ view[0:500] = b'x' * 500
603+
604+ Resizing or reallocating the underlying object (such as calling
605+ :meth: `bytearray.resize `) while a memoryview is exported raises
606+ :exc: `BufferError `. This is enforced regardless of threading.
0 commit comments