Image de couverture de Python sans GIL : explication du free-threaded

En un coup d’œil

Temps de lecture

~200 mots/min

Publié

il y a 1 mois

Jul 6, 2026

Vues

351

Total depuis le début

Python sans GIL : explication du free-threaded

Depuis que la plupart d'entre nous écrivons du Python, un fait a façonné notre manière de construire des programmes concurrents : le Global Interpreter Lock. Le GIL explique pourquoi les threads Python pour les tâches CPU-bound n'ont jamais offert de vrai parallélisme, pourquoi « utiliser multiprocessing » est devenu un réflexe, et pourquoi « Python est lent pour le travail parallèle » est devenu une idée reçue. Le Python sans GIL change la donne. Ce guide explique ce qu'est réellement le GIL, ce que sa suppression apporte et n'apporte pas, où elle aide, où elle pénalise, et comment envisager son adoption sans céder au battage médiatique dans un sens ou dans l'autre.

Ce que vous allez vraiment comprendre

  • Ce qu'est le GIL et pourquoi il a existé si longtemps
  • Ce que le Python « free-threaded » change: et ce qu'il ne change pas
  • Les compromis honnêtes : coût en single-thread et compatibilité des extensions C
  • Quand le free threading est un vrai gain par rapport à async ou multiprocessing
  • Une approche pragmatique pour l'évaluer sur vos propres charges de travail
i

Info

La réponse courte

Le GIL disparaît: en tant que version optionnelle officiellement supportée, pas comme nouveau défaut silencieux pour tout le monde du jour au lendemain. Le Python free-threaded est réel et pris en charge, mais c'est un choix délibéré avec des compromis, pas une accélération gratuite qu'on active partout sans réflexion.

Ce qu'est réellement le GIL

Le Global Interpreter Lock est un verrou unique à l'intérieur de CPython qui garantit qu'un seul thread exécute du bytecode Python à la fois. Il existe parce qu'il rendait l'interpréteur plus simple et plus rapide pour le code single-thread et qu'il gardait la gestion mémoire (comptage de références) sûre sans parsemer de verrous partout. Le prix à payer : les threads ne peuvent pas exécuter du code Python véritablement en parallèle. Deux threads effectuant un calcul lourd se passent le relais au lieu de tourner côte à côte, donc vous obtenez de la concurrence mais pas de parallélisme avec les threads.

With the GIL (CPU-bound work, 4 threads, 4 cores):
  Thread 1 ▓░░░▓░░░▓░░░   ← only one runs Python at a time
  Thread 2 ░▓░░░▓░░░▓░░     they take turns; 3 cores sit idle
  Thread 3 ░░▓░░░▓░░░▓
  Thread 4 ░░░▓░░░▓░░░

Free-threaded (no GIL):
  Thread 1 ▓▓▓▓▓▓▓▓▓▓▓▓   ← all four run in parallel
  Thread 2 ▓▓▓▓▓▓▓▓▓▓▓▓
  Thread 3 ▓▓▓▓▓▓▓▓▓▓▓▓     real use of all cores
  Thread 4 ▓▓▓▓▓▓▓▓▓▓▓▓

Ce que le free threading change

Dans une version free-threaded, le GIL est supprimé, donc plusieurs threads peuvent exécuter du bytecode Python simultanément sur plusieurs cœurs. Pour le travail CPU-bound que vous pouvez répartir entre threads, c'est le déblocage tant attendu : un vrai parallélisme à mémoire partagée sans la surcharge et la lourdeur de lancer des processus séparés et de sérialiser les données entre eux. Un seul processus, des objets partagés, tous vos cœurs.

Considérez une tâche CPU embarrassingly parallel. Avec la version standard, la paralléliser avec des threads ne vous apporte presque rien: le GIL sérialise le travail. Le même code sur la version free-threaded passe à l'échelle sur les cœurs :

import sys
from concurrent.futures import ThreadPoolExecutor

def crunch(n: int) -> int:           # pure CPU work — no I/O to hide behind
    total = 0
    for i in range(n):
        total += i * i
    return total

def run() -> None:
    with ThreadPoolExecutor(max_workers=8) as pool:
        list(pool.map(crunch, [20_000_000] * 8))

# Tell which world you're in at runtime:
print("GIL enabled:", sys._is_gil_enabled())   # True on standard build, False on 3.14t
run()
# Standard build: threads take turns — wall time ~= running all 8 tasks serially.
python3.14   bench.py     # GIL enabled: True

# Free-threaded build: threads run in parallel — wall time ~= one task (on 8 cores).
python3.14t  bench.py     # GIL enabled: False   ← the 't' build is the no-GIL one
PYTHON_GIL=0 python3.14t bench.py   # force the GIL off if an extension re-enabled it
Publicité

Ce que cela NE change PAS

Le free threading n'est pas un bouton magique « rendre Python rapide », et plusieurs espoirs courants sont mal placés.

Avantages

  • Vrai parallélisme pour les charges CPU-bound parallélisables par threads
  • Mémoire partagée: pas de sérialisation des données entre processus
  • Surcharge plus faible que multiprocessing pour le calcul sur nombreux cœurs

Inconvénients

  • Le code I/O-bound passait déjà bien à l'échelle avec threads/async: peu de gain ici
  • Les programmes single-thread peuvent tourner un peu plus lentement, pas plus vite
  • Cela n'accélère pas le code séquentiel ; seul le travail parallélisable en bénéficie
  • Cela réintroduit les classiques data races: l'état partagé nécessite désormais une vraie attention

Avertissement

Sans GIL, la sécurité des threads vous incombe à nouveau

Le GIL protégeait accidentellement beaucoup de code bâclé manipulant un état partagé. Sans lui, deux threads qui modifient le même objet s'exécutent vraiment en même temps, donc des conditions de concurrence auparavant masquées peuvent apparaître. Le code free-threaded exige la même discipline de verrouillage que n'importe quel autre langage véritablement parallèle. C'est une fonctionnalité qui vient avec des responsabilités.

Voici le genre de bogue que le GIL cachait. Deux threads qui incrémentent un compteur partagé effectuent une lecture-modification-écriture qui peut s'entrelacer, donc des incréments sont perdus: et la correction est la même que dans tout langage parallèle : protégez l'état mutable partagé avec un verrou.

import threading

# ❌ Racy without the GIL: counter += 1 is read, add, write — and can interleave.
counter = 0
def unsafe():
    global counter
    for _ in range(1_000_000):
        counter += 1          # two threads can both read the same value → lost updates

# ✅ Correct: a lock makes the update atomic.
counter = 0
lock = threading.Lock()
def safe():
    global counter
    for _ in range(1_000_000):
        with lock:
            counter += 1      # only one thread mutates at a time

# Better still: avoid shared mutable state. Have each thread return its own
# partial result and combine them at the end — no lock, no contention.

Les deux coûts honnêtes

1. Surcharge en single-thread

Supprimer le GIL nécessite des changements dans la gestion mémoire qui peuvent rendre le code single-thread un peu plus lent qu'avec la version standard. Si votre programme est principalement séquentiel, la version free-threaded risque de vous coûter des performances au lieu de vous en faire gagner. Le pari n'est gagnant que lorsque vous parallélisez véritablement du travail CPU sur plusieurs threads.

2. Compatibilité des extensions C

Une énorme partie de la valeur de Python réside dans les extensions C: la pile scientifique, les pilotes de base de données, les analyseurs syntaxiques. Beaucoup supposent que le GIL existe et ont besoin de mises à jour pour être sûres et correctes sans lui. L'écosystème migre activement, mais vous ne pouvez pas supposer qu'une extension arbitraire est prête pour le free threading. Cette courbe de compatibilité, plus que tout, détermine la vitesse à laquelle le monde sans GIL devient pratique pour les applications courantes.

Choisir le bon outil de concurrence

Le free threading ne remplace pas les autres outils: il comble un manque spécifique. Adaptez l'outil au goulot d'étranglement.

1

I/O-bound (réseau, disque, appels DB) ?

Utilisez async ou des threads classiques. Le GIL n'a jamais été votre problème ici ; vous attendez, vous ne calculez pas. Le free threading n'apporte pas grand-chose.

2

CPU-bound et parallélisable ?

C'est le terrain de prédilection du free threading: et auparavant celui de multiprocessing. Le free threading peut le faire avec de la mémoire partagée et moins de surcharge, une fois que vos extensions le supportent.

3

Code CPU-bound mais extensions pas prêtes ?

Restez pour l’instant sur le multiprocessing. L’isolation par processus contourne le GIL à l’ancienne et reste une solution parfaitement valable.

4

Application majoritairement monothread ?

Gardez la version standard. La version sans GIL risquerait de dégrader les performances monothread sans apporter de gain parallèle.

1 processus

tous vos cœurs: la promesse de Python sans GIL pour le calcul CPU parallèle

Comment l’évaluer concrètement

N’adoptez pas le mode sans GIL par principe ou par crainte. Mesurez. Déployez la version sans GIL dans un environnement de test, exécutez votre vraie charge CPU et comparez le temps réel et la justesse des résultats avec la version standard et votre approche multiprocessing actuelle. Surtout, vérifiez que chaque extension C dont vous dépendez est compatible avec le mode sans GIL avant d’envisager la production.

💡

Astuce

Ajoutez l’interpréteur sans GIL comme cible CI parallèle. Exécuter votre suite de tests sur les deux versions fait remonter automatiquement les incompatibilités d’extensions et les nouvelles conditions de concurrence, transformant la question « notre code est-il sûr sans GIL ? » en un simple voyant vert ou rouge.

Publicité

Alors, le GIL disparaît-il vraiment ?

Oui: mais il faut en comprendre la portée. Le GIL a disparu dans une version officiellement prise en charge, ce qui constitue un véritable tournant historique et le socle du futur parallèle de Python. Dans la version 3.14, ce n’est pas le mode par défaut hérité silencieusement par tout le monde, car le coût en monothread et la migration des extensions C rendent ce changement prématuré. Pour le dire honnêtement : l’époque où « Python ne peut pas faire de vrai parallélisme » touche à sa fin, progressivement, et le rythme dépend plus de l’adaptation de l’écosystème que du langage lui-même.

! Erreurs fréquentes à éviter

  • S’attendre à ce que la version sans GIL accélère le code lié aux entrées-sorties.

    Le GIL n’a jamais été le goulot d’étranglement dans ce cas: utilisez l’asynchrone ou les threads ; le mode sans GIL aide pour le travail CPU.

  • Supposer que le code threadé existant est automatiquement sûr sans le GIL.

    Des conditions de concurrence masquées par le GIL peuvent désormais apparaître: protégez l’état mutable partagé avec des verrous.

  • Adopter le mode sans GIL par principe, sans mesurer.

    Comparez votre charge réelle avec la version standard et le multiprocessing avant de vous engager.

  • Ignorer la compatibilité des extensions C.

    Vérifiez que chaque dépendance native prend en charge le mode sans GIL ; beaucoup supposent encore la présence du GIL.

? Questions fréquentes

Qu’est-ce que le GIL en termes simples ? +

Un verrou unique dans CPython qui ne laisse qu’un seul thread exécuter du bytecode Python à la fois. Il simplifiait l’interpréteur et la gestion mémoire, mais empêchait les threads d’exécuter du code Python véritablement en parallèle.

Supprimer le GIL rend-il Python plus rapide ? +

Uniquement pour le travail CPU que vous pouvez répartir sur plusieurs threads. Le code monothread peut même s’exécuter un peu plus lentement avec la version sans GIL, ce n’est donc pas une accélération universelle.

Dois-je utiliser des threads, de l’asynchrone ou du multiprocessing maintenant ? +

Asynchrone/threads pour les entrées-sorties, mode sans GIL pour le calcul CPU parallèle (une fois les extensions compatibles), multiprocessing si vos extensions ne sont pas encore prêtes, et la version standard pour les applications majoritairement monothread.

Python sans GIL est-il prêt pour la production ? +

Il est officiellement pris en charge, mais l’adoption est conditionnée par la compatibilité des extensions C et le coût en monothread. Évaluez-le délibérément pour les charges parallèles plutôt que de l’activer partout.

Comment savoir quelle version j’exécute ? +

Vérifiez sys._is_gil_enabled() à l’exécution, ou lancez l’interpréteur sans GIL (par exemple python3.14t). La version sans GIL indique que le GIL est désactivé.

Succès

Un fondement, pas une ligne d’arrivée

Python sans GIL ouvre une porte qui était verrouillée depuis trente ans. Franchissez-la avec méthode: mesurez votre charge, vérifiez vos dépendances et respectez la sécurité des threads: et vous obtiendrez un vrai parallélisme multi-cœur en Python pur. Cela mérite d’être bien fait plutôt que précipité.

Icône de l'application Android Learn Python

Entraînez-vous en mobilité

Apprenez Python, l’application Android gratuite

Chaque sujet de cette série est aussi dans l’application : leçons courtes, exemples exécutables, quiz, mini-projets et un environnement Python hors ligne qui fonctionne sur votre téléphone.

Bishrul Haq

Written by

Bishrul Haq

Software engineer writing practical tutorials on Laravel, PHP, Python, and the tools behind real projects. More about me

Newsletter

Want more posts like this?

Get practical software notes and tutorials delivered when something new is published.

Pas de spam. Désinscription à tout moment.

Qu’en avez-vous pensé ?

Commentaires

0
Se connecter ou Créer un compte pour participer à la discussion et réagir à cet article.

Aucun commentaire pour l’instant. Soyez la première personne à donner votre avis.

Related posts

Fonctionnalités essentielles de Pandas en Python : astuces et fonctionnalités

Pandas est l'une de mes bibliothèques Python préférées. Elle est très utile pour visualiser les données de manière claire et structurée. De nos jours, Pandas est largement utilisée en science des données, en apprentissage automatique et dans d'autres domaines.

il y a 6 ans

Comment récupérer des données de Twitter avec Tweepy en Python ?

Pour commencer à travailler avec Python, vous devez avoir Python installé sur votre ordinateur. Si ce n’est pas encore fait, rendez-vous sur le site officiel de Python pour l’installer.

il y a 6 ans

Prédire le revenu par habitant des États-Unis avec la régression linéaire

Python permet de prédire et d'analyser des données à l'aide de la régression linéaire. La régression linéaire est l'une des techniques fondamentales de machine learning ou de statistique conçues pour résoudre des problèmes complexes.

il y a 6 ans

Algorithmes de tri essentiels pour les étudiants en informatique

Les algorithmes sont couramment enseignés dans les cursus d'informatique et de génie logiciel, en licence ou en master. Certains les trouvent difficiles à comprendre parce qu'ils les apprennent par cœur.

il y a 6 ans

Python 3.14 pour les projets réels : Free Threading, JIT, t-strings et Zstandard

Ce qui compte vraiment dans Python 3.14 pour la production : les builds officiels sans GIL, le JIT expérimental, les t-strings pour une interpolation sécurisée, Zstandard dans la bibliothèque standard et un plan d'adoption à faible risque.

il y a 1 mois