-
-
Notifications
You must be signed in to change notification settings - Fork 33.3k
gh-140374: Add glossary entries related to multithreading #140375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
64157d0
0825a98
3f44be0
568d201
22cf4f6
bd7b731
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -134,6 +134,16 @@ Glossary | |||||||||||||||||||||
| iterator's :meth:`~object.__anext__` method until it raises a | ||||||||||||||||||||||
| :exc:`StopAsyncIteration` exception. Introduced by :pep:`492`. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| atomic operation | ||||||||||||||||||||||
| An operation that completes as a single indivisible unit without | ||||||||||||||||||||||
| interruption from other threads. Atomic operations are critical for | ||||||||||||||||||||||
| :term:`thread-safe` programming because they cannot be observed in a | ||||||||||||||||||||||
| partially completed state by other threads. In the | ||||||||||||||||||||||
| :term:`free-threaded <free threading>` build, elementary operations | ||||||||||||||||||||||
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||
| should generally be assumed to be atomic unless the documentation | ||||||||||||||||||||||
| explicitly states otherwise. See also :term:`race condition` and | ||||||||||||||||||||||
| :term:`data race`. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| attached thread state | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| A :term:`thread state` that is active for the current OS thread. | ||||||||||||||||||||||
|
|
@@ -289,6 +299,23 @@ Glossary | |||||||||||||||||||||
| advanced mathematical feature. If you're not aware of a need for them, | ||||||||||||||||||||||
| it's almost certain you can safely ignore them. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| concurrency | ||||||||||||||||||||||
| The ability of different parts of a program to be executed out-of-order | ||||||||||||||||||||||
| or in partial order without affecting the outcome. This allows for | ||||||||||||||||||||||
| multiple tasks to make progress during overlapping time periods, though | ||||||||||||||||||||||
| not necessarily simultaneously. In Python, concurrency can be achieved | ||||||||||||||||||||||
| through :mod:`threading` (using OS threads), :mod:`asyncio` (cooperative | ||||||||||||||||||||||
| multitasking), or :mod:`multiprocessing` (separate processes). | ||||||||||||||||||||||
| See also :term:`parallelism`. | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like the "out-of-order" definition. Concurrency is about things happening or being performed at the same time (in both computing and non-computing contexts). Something like: The ability of a computer program to perform multiple tasks at the same time. Python provides libraries for writing programs that make use of different forms of concurrency. :mod: |
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| concurrent modification | ||||||||||||||||||||||
| When multiple threads modify shared data at the same time without | ||||||||||||||||||||||
| proper synchronization. Concurrent modification can lead to | ||||||||||||||||||||||
| :term:`data races <data race>` and corrupted data. In the | ||||||||||||||||||||||
| :term:`free-threaded <free threading>` build, built-in types like | ||||||||||||||||||||||
| :class:`dict`, :class:`list`, and :class:`set` use internal locks | ||||||||||||||||||||||
| to protect against concurrent modifications. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| context | ||||||||||||||||||||||
| This term has different meanings depending on where and how it is used. | ||||||||||||||||||||||
| Some common meanings: | ||||||||||||||||||||||
|
|
@@ -343,6 +370,16 @@ Glossary | |||||||||||||||||||||
| :keyword:`async with` keywords. These were introduced | ||||||||||||||||||||||
| by :pep:`492`. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| critical section | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should define critical section, at least not for now. The way we use I'd rather talk about those details in the C API docs instead of the Python glossary. |
||||||||||||||||||||||
| A section of code that accesses shared resources and must not be | ||||||||||||||||||||||
| executed by multiple threads simultaneously. Critical sections are | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should emphasize that critical sections are purely a concept in the C API and aren't exposed in the python language There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
| typically protected using :term:`locks <lock>` or other | ||||||||||||||||||||||
| :term:`synchronization primitives <synchronization primitive>` to | ||||||||||||||||||||||
| ensure :term:`thread-safe` access. In the C API, critical sections | ||||||||||||||||||||||
| on shared objects can be protected using :c:macro:`Py_BEGIN_CRITICAL_SECTION` | ||||||||||||||||||||||
| and :c:macro:`Py_END_CRITICAL_SECTION`. See also :term:`lock` and | ||||||||||||||||||||||
| :term:`race condition`. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| CPython | ||||||||||||||||||||||
| The canonical implementation of the Python programming language, as | ||||||||||||||||||||||
| distributed on `python.org <https://www.python.org>`_. The term "CPython" | ||||||||||||||||||||||
|
|
@@ -363,6 +400,24 @@ Glossary | |||||||||||||||||||||
| the :term:`cyclic garbage collector <garbage collection>` is to identify these groups and break the reference | ||||||||||||||||||||||
| cycles so that the memory can be reclaimed. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| data race | ||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are only talking about native code (C or C++ or Rust or whatever), maybe we should leave this out of the glossary for now. |
||||||||||||||||||||||
| A situation where multiple threads access the same memory location | ||||||||||||||||||||||
| concurrently, at least one of the accesses is a write, and the threads | ||||||||||||||||||||||
| do not use any synchronization to control their access. Data races | ||||||||||||||||||||||
| lead to :term:`non-deterministic` behavior and can cause data corruption. | ||||||||||||||||||||||
| Proper use of :term:`locks <lock>` and other :term:`synchronization primitives | ||||||||||||||||||||||
| <synchronization primitive>` prevents data races. See also | ||||||||||||||||||||||
| :term:`race condition` and :term:`thread-safe`. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| deadlock | ||||||||||||||||||||||
| A situation where two or more threads are unable to proceed because | ||||||||||||||||||||||
| each is waiting for the other to release a resource. For example, | ||||||||||||||||||||||
| if thread A holds lock 1 and waits for lock 2, while thread B holds | ||||||||||||||||||||||
| lock 2 and waits for lock 1, both threads will wait indefinitely. | ||||||||||||||||||||||
| Deadlocks can be avoided by always acquiring multiple :term:`locks <lock>` | ||||||||||||||||||||||
| in a consistent order or by using timeout-based locking. See also | ||||||||||||||||||||||
| :term:`lock` and :term:`reentrant`. | ||||||||||||||||||||||
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| decorator | ||||||||||||||||||||||
| A function returning another function, usually applied as a function | ||||||||||||||||||||||
| transformation using the ``@wrapper`` syntax. Common examples for | ||||||||||||||||||||||
|
|
@@ -662,6 +717,16 @@ Glossary | |||||||||||||||||||||
| requires the GIL to be held in order to use it. This refers to having an | ||||||||||||||||||||||
| :term:`attached thread state`. | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| global state | ||||||||||||||||||||||
| Data that is accessible throughout a program, such as module-level | ||||||||||||||||||||||
| variables, class variables, or C static variables in :term:`extension modules | ||||||||||||||||||||||
| <extension module>`. In multi-threaded programs, global state shared | ||||||||||||||||||||||
| between threads typically requires synchronization to avoid | ||||||||||||||||||||||
| :term:`race conditions <race condition>`. In the | ||||||||||||||||||||||
|
||||||||||||||||||||||
| :term:`race conditions <race condition>`. In the | |
| :term:`race conditions <race condition>` and :term:`data races <data race>`. In the |
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| non-deterministic | |
| Behavior where the outcome of a program can vary between executions with | |
| the same inputs. In multi-threaded programs, non-deterministic behavior | |
| often results from :term:`race conditions <race condition>` where the | |
| relative timing or interleaving of threads affects the result. | |
| :term:`Data races <data race>` are a common cause of non-deterministic | |
| bugs. Proper synchronization using :term:`locks <lock>` and other | |
| the same inputs. An example of non-deterministic behavior | |
| are :term:`race conditions <race condition>`. | |
| Proper synchronization using :term:`locks <lock>` and other |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just removed the sentence @ngoldbaum mentioned. Does it read okay like this? I'd like to keep the mention of relative timing and interleaving in.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| The simultaneous execution of multiple operations on different CPU cores. | |
| The simultaneous execution of operations on multiple processors. |
To allow for GPUs
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like:
Executing multiple operations at the same time (e.g., on multiple CPU cores). In Python builds with the :term:global interpreter lock (GIL), only one thread runs Python bytecode at a time, so taking advantage of multiple CPU cores typically involves multiple processes (e.g., :term:multiprocessing) or native extensions that release the GIL. In :term:free-threaded` Python, multiple Python threads can run Python code simultaneously on different cores.
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we elsewhere define global state as including per-module state?
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
lysnikolaou marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to rework the first sentence a bit. We talk about thread-safe modules and data structures (classes), not just "code"
Maybe something like:
A module, function, or class that behaves correctly when used by multiple threads concurrently.
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| to provide thread-safe operations, though this doesn't guarantee safety | |
| to make many operations thread-safe, although thread safety is not necessarily guaranteed |
The way you have this line now is a little confusing IMO, since it says that everything is thread-safe, but no guarantees. I think the way I rephrased it here is correct and leaves it a little clearer that lots of stuff is thread-safe but there are exceptions.
When eventually we have a full listing of what exactly is thread-safe and thread-unsafe in the APIs of the builtins, we can link to that here, maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've seen "interrupt" in various definitions online, but I think "interrupt" is confusing in this context. I'm not really sure what it refers to here and the granularity of "atomic" vs. "interrupt" can be different. For example, a thread performing an atomic operation with locks can rescheduled (interrupted) by the OS without breaking atomicity.
I like this definition (from ChatGPT):
An operation that appears to execute as a single, indivisible step: no other thread can observe it half-done, and its effects become visible all at once. Python does not guarantee that ordinary high-level statements are atomic (for example, x += 1 performs multiple bytecode operations and is not atomic). Atomicity is only guaranteed where explicitly documented (e.g., operations performed while holding a lock, or methods of synchronization primitives such as those in threading and queue).