Skip to content

Commit 2c21546

Browse files
committed
[mypyc] Update documentation of race conditions under free threading (#21726)
Mypyc now gives additional thread safety guarantees.
1 parent a9f62a3 commit 2c21546

2 files changed

Lines changed: 29 additions & 35 deletions

File tree

mypyc/doc/differences_from_python.rst

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -293,40 +293,26 @@ attribute tends to be faster than a plain global variable in compiled code::
293293
Free threading
294294
--------------
295295

296-
Mypyc supports free threading, but it doesn't provide the exact
297-
memory safety guarantees as Python in compiled modules under
298-
free threading when there are race conditions.
299-
300-
Additionally, optimized primitive operations in compiled code may have
301-
different atomicity properties compared to CPython. Use explicit
302-
synchronization if code depends on operations being atomic. This is
303-
already the recommended approach for normal Python code.
304-
305-
Currently, compiled code must ensure that proper synchronization is
306-
used to prevent data races involving non-final attributes in native
307-
classes, unless the attribute has a value type such as ``bool``,
308-
``float`` or ``i64``. You can use explicit
309-
synchronization, such as via
310-
:ref:`librt.threading.Lock <librt-threading-lock>` (or
311-
:py:class:`threading.Lock`, which is less efficient than
312-
``librt.threading.Lock``) if there is a possibility of such a data
313-
race.
296+
Mypyc supports free threading. However, optimized primitive operations in
297+
compiled code may have different atomicity properties compared to CPython.
298+
Use explicit synchronization if code depends on operations being atomic and
299+
race conditions are possible. This is already the recommended approach for
300+
normal Python code. You can often use :ref:`librt.threading.Lock <librt-threading-lock>`
301+
(or :py:class:`threading.Lock`, which is less efficient than
302+
``librt.threading.Lock``) to fix data races.
303+
304+
Since mypyc 2.3, the vast majority of operations are memory safe even if
305+
there are race conditions (unlike earlier mypyc releases). This includes
306+
list operations and access to native instance attributes (except for
307+
a few less common use cases that will be fixed in future releases).
314308

315309
.. note::
316310

317-
We are working on improving memory safety in free-threading
318-
builds of Python, and hope to make all normal Python features
319-
memory safe, while providing more efficient but less safe
320-
opt-in, non-standard features.
321-
322-
As libraries often won't be able to control the concurrent access by
323-
user code, we recommend that modules document that multi-threaded
324-
access is only supported via public interfaces that ensure correct
325-
synchronization. Marking attributes as internal using an underscore
326-
attribute prefix is another possibility, but this is not enforced at
327-
runtime. Another option is to document that multithreaded access is
328-
not supported, or that particular objects should not be used from
329-
multiple threads concurrently.
311+
Operations that aren't safe under race conditions in interpreted CPython
312+
are not expected to be memory safe in compiled code either.
313+
Some :ref:`librt <librt>` features are heavily optimized for performance and
314+
don't guarantee memory safety when there are race conditions
315+
(notably the :ref:`vec <librt-vecs>` type).
330316

331317
It's always safe to perform read-only operations concurrently. Using
332318
objects with final attributes and tuple objects can help prevent

mypyc/doc/librt_vecs.rst

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _librt-vecs:
2+
13
librt.vecs
24
==========
35

@@ -198,15 +200,21 @@ with no unnecessary temporary objects.
198200
Thread safety
199201
-------------
200202

203+
The ``vec`` type is heavily optimized for performance, and this means that ``vec``
204+
gives fewer thread safety guarantees than built-in types such as ``list``.
205+
``vec`` is a lower-level type where implicit synchronization would have a very
206+
significant performance cost. However, since vec lengths are immutable, some race
207+
conditions that lists can be susceptible to are not possible with vecs.
208+
201209
In free-threaded Python builds, it's unsafe to write or modify an item if other
202210
threads might be concurrently accessing *the same item*. For example, writing ``v[4]``
203211
is not safe to do if another thread might be reading ``v[4]``. Similarly, two
204212
threads concurrently calling ``append`` or ``remove`` on the same vec object is not safe.
205213

206-
This is different from list objects, since vec is a lower-level type where implicit
207-
synchronization would have a significant performance cost. However, since vec lengths
208-
are immutable, some race conditions that lists can be susceptible to are not possible
209-
with vecs.
214+
Similarly, assigning to an instance attribute of a native class with a ``vec`` type
215+
is unsafe if another thread might be accessing the same attribute concurrently
216+
(in a free-threaded Python build only). Using ``Final`` attributes is a way
217+
to prevent this race condition, since ``Final`` attributes cannot be rebound.
210218

211219
Implementation details
212220
----------------------

0 commit comments

Comments
 (0)