En Python, la bibliothèque standard fournit le module threading pour la multithreading. Les threads permettent d'exécuter plusieurs opérations en parallèle dans un même processus. Cependant, dans l'implémentation standard de Python (CPython), il existe un mécanisme GIL (Global Interpreter Lock) — un verrou global de l'interpréteur, qui n'autorise qu'un seul thread à exécuter du bytecode Python à la fois.
Cela signifie qu'en CPython, la multithreading ne permet pas d'atteindre un véritable parallélisme lors de l'exécution de code Python au niveau du processeur ; le parallélisme est utile uniquement pour les tâches liées à l'attente (I/O-bound). Pour les tâches CPU-bound, il est recommandé d'utiliser le module multiprocessing, qui lance plusieurs processus et contourne le GIL.
Exemple :
import threading def worker(): print('Début') # calculs lourds print('Fin') threads = [threading.Thread(target=worker) for _ in range(5)] for t in threads: t.start() for t in threads: t.join()
Pour le parallélisme lors de calculs intensifs, utilisez multiprocessing :
from multiprocessing import Pool def square(x): return x*x with Pool(4) as p: print(p.map(square, [1, 2, 3, 4]))
La multithreading en Python peut-elle accélérer l'exécution des tâches compute-heavy ?
Réponse : Non, en raison du GIL dans l'implémentation standard de Python (CPython), les threads n'apporteront pas d'amélioration des performances pour les tâches CPU-bound ; pour ces tâches, utilisez multiprocessing ou des implémentations tierces de l'interpréteur (comme Jython, IronPython) qui ne possèdent pas de GIL.
Histoire
Dans un projet de traitement de grandes quantités de données, l'équipe a essayé d'accélérer les calculs en utilisant des threads (
threading). Au lieu de gagner en rapidité, le temps de traitement a augmenté, car le GIL empêchait les threads de travailler en parallèle ; après être passés àmultiprocessing, la tâche a été résolue.
Histoire
Un développeur tentait de télécharger simultanément de gros fichiers et de les traiter dans plusieurs threads, mais se heurte souvent à un "deadlock" en raison d'une utilisation imprudente de variables partagées sans verrouillage (sécurité des threads).
Histoire
Sur un serveur backend, le traitement de lourdes requêtes était mis en œuvre dans un pool de threads. Avec l'augmentation de la charge, le serveur a commencé à "geler" — il s'est avéré que la plupart du temps, les threads passaient en attente de l'exécution de code Python en raison du GIL, bien que les requêtes n'étaient pas liées à une I/O intensive.