In Python biedt de standaardbibliotheek de module threading voor multithreading. Threads maken het mogelijk om meerdere operaties parallel uit te voeren binnen één proces. Echter, in de standaardimplementatie van Python (CPython) is er een mechanisme genaamd GIL (Global Interpreter Lock) — een wereldwijde vergrendeling van de interpreter, die slechts één thread tegelijk toestaat om Python-bytecode uit te voeren.
Dit betekent dat in CPython multithreading geen echte parallelisme mogelijk maakt bij het uitvoeren van Python-code op CPU-niveau; parallelisme is alleen nuttig voor taken die met wachten te maken hebben (I/O-bound). Voor CPU-bound taken wordt aangeraden om de module multiprocessing te gebruiken, die meerdere processen start en de GIL omzeilt.
Voorbeeld:
import threading def worker(): print('Start') # zware berekeningen print('Einde') threads = [threading.Thread(target=worker) for _ in range(5)] for t in threads: t.start() for t in threads: t.join()
Voor parallelisme bij intensieve berekeningen, gebruik multiprocessing:
from multiprocessing import Pool def square(x): return x*x with Pool(4) as p: print(p.map(square, [1, 2, 3, 4]))
Kan multithreading in Python de uitvoering van compute-heavy taken versnellen?
Antwoord: Nee, vanwege de GIL in de standaardimplementatie van Python (CPython) zullen threads geen prestatieverbetering opleveren voor CPU-bound taken; voor dergelijke taken gebruik je multiprocessing of alternatieve implementaties van de interpreter (zoals Jython, IronPython), die geen GIL hebben.
Verhaal
In een project voor het verwerken van grote hoeveelheden gegevens probeerde het team de berekeningen te versnellen met behulp van threads (
threading). In plaats van versnelling nam de verwerkingstijd toe, omdat de GIL de threads niet in staat stelde om parallel te werken; na overstappen opmultiprocessingwerd de taak opgelost.
Verhaal
Een ontwikkelaar probeerde tegelijkertijd grote bestanden te downloaden en deze in meerdere threads te verwerken, maar kwam vaak vast te zitten in een "deadlock" door ondoordacht gebruik van gedeelde variabelen zonder vergrendelingen (thread safety).
Verhaal
Op de backend-server werden zware verzoeken verwerkt in een thread-pool. Toen de belasting toenam, begon de server te "bevriezen" — het bleek dat de meeste tijd werd besteed door de threads in afwachting van de uitvoering van Python-code vanwege de GIL, hoewel de verzoeken niet gerelateerd waren aan intensieve I/O.