Build1 publisher2 min readPublished
Summit proposal offers deadlock-free tasks to fill PEP 779's unmet high-level concurrency primitives requirement
Tobias Wrigstad, Fridtjof Stoldt and Donghee Na proposed Behavior-Oriented Concurrency to meet PEP 779's one unmet free-threading requirement. Its scheduler would turn deadlocks and data races into exceptions before code runs.
The Engineer · Build desk

What happened
- The Steering Council's PEP 779 acceptance asked the core team for primitives usable without a deep understanding of the underlying threading mechanism.
- Free-threaded Python is reached today through plain threads, which leave deadlocks and race conditions for the user to manage.
- In BOC, a @when decorator declares which data-aware mutexes, called Cowns, a task depends on, and the task can only touch data through them.
- On the presenters' speed, simplicity and safety chart, free-threaded Python sits beside C: simple and fast, with correctness left to the programmer.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- cost Existing thread-and-lock code would not carry over as written: each parallel section would need its shared data assigned to declared cowns before the scheduler could reason about it.
- capability Placement would move into the runtime, so users would stop choosing between spawning a thread and a subinterpreter for each piece of parallel work.
- decision Teams adopting free-threaded builds now still write lock discipline by hand, and should plan for the recommended interface to change once the Steering Council's other acceptance tasks are stable.
The difference from threading.Lock is ownership. A Cown knows which data it protects, so it can make sure only one task at a time touches that data [14]. Every task names its cowns before it runs, and that lets the runtime build a dependency graph across all tasks and data [15]. Tasks are lightweight and can run on any core [13]. Give the graph to a scheduler and, according to the presenters, the program gets no deadlocks, no data races and good "locking discipline" [16]. The scheduler would also turn detected deadlocks or races into exceptions, found ahead of execution [18].
Each of those properties depends on the access rule holding. In my view, enforcement is the first thing to test. A task that reaches shared state through a module global or a closure would sit outside the graph the scheduler reasons about. The summit write-up does not show how the rule is enforced. It also does not name a PEP, a target release, or whether BOC would live in the concurrent package the Steering Council recommended [20].
The ranking behind BOC comes from three axes the presenters called "sometimes at odds with each other": speed, simplicity and safety [7]. C is fast and simple but relies on programmer discipline. Erlang copies data between actors and gives up speed [8]. Rust is fast and safe, but "you'll find yourself often fighting with the borrow checker," the presenters said [9]. On their chart the GIL "only protects the runtime" [10]. Subinterpreters get isolation, but data copying makes them neither simple nor fast [10]. For a high-level model, they said "safety would be a priority and then performance", with "simplicity as third" [11]. "Simplicity is at odds with performance," they said [12].
Most people first meet parallelism through threads, in school and in textbooks [19]. Familiarity is most of the case for them. I think the presenters' order is right for a standard-library default. A race reported as an exception before the code runs costs less to fix than one found later as wrong output.
Wrigstad and Stoldt presented "Fearless Concurrency" at the 2025 summit [2], so 2026 is their second consecutive year on the subject [1]. Donghee Na joined them this year [1].
What to watch
- A PEP or draft specification for Behavior-Oriented Concurrency, and whether it targets the stdlib concurrent package.
- How BOC enforces the rule that tasks touch data only through declared cowns, including data reached via globals, closures or C extensions.
- A Steering Council statement that the other PEP 779 tasks are stable, the point at which it asked for primitives work to be prioritized.