Super quick question about subinterpreters. The docs state “no implicit threads”; I just wanted to confirm whether each subinterpreter manages its own garbage collection thread? If not, how do subinterpreters collect objects involved in reference cycles?
I might get corrected, but I think there’s no separate GC thread also without subinterpreters.
As in, the thread that detects the need to run the GC becomes the GC thread, without any one thread being dedicated to the task.
And this should be the case for both GIL-enabled and -disabled builds.
The CPython implementation creates only a single thread. Applications can create any number of threads, but, if they don’t, you can use your platform’s version of a process viewer to verify that only a single thread ever exists (the thread that runs the “main process”).
Subinterpreters don’t change this. But, by design, they don’t share state, and each effectively has its own GIL (global interpreter lock). The thread that creates a subinterpreter is “taken over” for the life of the subinterpreter. If you create your own threads, and start a subinterpreter in each, then those subinterpreters can run in parallel “for real”.
But they overwhelmingly don’t share state, and each has its own GIL, so each can run cyclic gc independently and simultaneously.
This isn’t the aim of subinterpreters. Their aim is isolation, That they can be used to support a form of “true concurrency” is a consequence of pursuing isolation.
Got it. For some reason I was under the impression that by default CPython spawns and uses a dedicated thread for cyclic garbage collection; I understand now this is not the case. Thanks for the corrections.
It might’ve been my previous Java experience creating a false memory or something. Although I see PEP 556 was proposed once upon a time to do something like this.