Multithreading in Python met voorbeeld:leer GIL in Python
Met de programmeertaal Python kunt u multiprocessing of multithreading gebruiken. In deze tutorial leer je hoe je multithreaded applicaties schrijft in Python.
Wat is een discussielijn?
Een thread is een uitvoeringseenheid bij gelijktijdige programmering. Multithreading is een techniek waarmee een CPU veel taken van één proces tegelijkertijd kan uitvoeren. Deze threads kunnen afzonderlijk worden uitgevoerd terwijl ze hun procesbronnen delen.
Wat is een proces?
Een proces is in feite het programma in uitvoering. Wanneer u een toepassing op uw computer start (zoals een browser of teksteditor), maakt het besturingssysteem een proces aan.
Wat is multithreading in Python?
Multithreading in Python programmeren is een bekende techniek waarbij meerdere threads in een proces hun dataruimte delen met de hoofdthread, wat het delen van informatie en communicatie binnen threads gemakkelijk en efficiënt maakt. Draden zijn lichter dan processen. Multi-threads kunnen afzonderlijk worden uitgevoerd terwijl ze hun procesbronnen delen. Het doel van multithreading is om meerdere taken en functiecellen tegelijkertijd uit te voeren.
In deze tutorial leer je,
- Wat is een draad?
- Wat is een proces?
- Wat is multithreading?
- Wat is multiprocessing?
- Python Multithreading versus Multiprocessing
- Waarom multithreading gebruiken?
- Python MultiThreading
- De draad- en draadmodules
- De draadmodule
- De inrijgmodule
- Deadlocks en racevoorwaarden
- Draden synchroniseren
- Wat is GIL?
- Waarom was GIL nodig?
Wat is multiprocessing?
Met multiprocessing kunt u meerdere niet-gerelateerde processen tegelijkertijd uitvoeren. Deze processen delen hun bronnen niet en communiceren niet via IPC.
Python Multithreading versus Multiprocessing
Overweeg dit scenario om processen en threads te begrijpen:Een .exe-bestand op uw computer is een programma. Wanneer u het opent, laadt het besturingssysteem het in het geheugen en voert de CPU het uit. De instantie van het programma dat nu draait, wordt het proces genoemd.
Elk proces heeft 2 fundamentele componenten:
- De code
- De gegevens
Nu kan een proces een of meer subonderdelen bevatten die threads worden genoemd. Dit hangt af van de OS-architectuur. Je kunt een thread beschouwen als een onderdeel van het proces dat afzonderlijk door het besturingssysteem kan worden uitgevoerd.
Met andere woorden, het is een stroom van instructies die onafhankelijk door het besturingssysteem kan worden uitgevoerd. Threads binnen een enkel proces delen de gegevens van dat proces en zijn ontworpen om samen te werken om parallellisme te vergemakkelijken.
Waarom multithreading gebruiken?
Met multithreading kunt u een toepassing opsplitsen in meerdere subtaken en deze taken tegelijkertijd uitvoeren. Als u multithreading op de juiste manier gebruikt, kunnen uw applicatiesnelheid, prestaties en weergave allemaal worden verbeterd.
Python MultiThreading
Python ondersteunt constructies voor zowel multiprocessing als multithreading. In deze zelfstudie richt je je voornamelijk op het implementeren van multithreaded toepassingen met python. Er zijn twee hoofdmodules die kunnen worden gebruikt om threads in Python af te handelen:
- De thread module, en
- De threading module
In python is er echter ook iets dat een global interpreter lock (GIL) wordt genoemd. Het zorgt niet voor veel prestatiewinst en kan zelfs verminderen de prestaties van sommige toepassingen met meerdere threads. Je zult er alles over leren in de komende secties van deze tutorial.
De modules Draad en Draadsnijden
De twee modules waarover u in deze zelfstudie leert, zijn de thread-module en de threading-module .
De threadmodule is echter al lang verouderd. Vanaf Python 3 is het als verouderd aangemerkt en is het alleen toegankelijk als __thread voor achterwaartse compatibiliteit.
U moet de threading op een hoger niveau gebruiken module voor toepassingen die u wilt implementeren. De thread-module is hier alleen behandeld voor educatieve doeleinden.
De draadmodule
De syntaxis om een nieuwe thread te maken met behulp van deze module is als volgt:
thread.start_new_thread(function_name, arguments)
Oké, nu heb je de basistheorie behandeld om te beginnen met coderen. Open dus uw IDLE of een notitieblok en typ het volgende in:
import time import _thread def thread_test(name, wait): i = 0 while i <= 3: time.sleep(wait) print("Running %s\n" %name) i = i + 1 print("%s has finished execution" %name) if __name__ == "__main__": _thread.start_new_thread(thread_test, ("First Thread", 1)) _thread.start_new_thread(thread_test, ("Second Thread", 2)) _thread.start_new_thread(thread_test, ("Third Thread", 3))
Sla het bestand op en druk op F5 om het programma uit te voeren. Als alles correct is gedaan, is dit de uitvoer die u zou moeten zien:
In de komende secties leer je meer over raceomstandigheden en hoe je ermee om moet gaan
CODE UITLEG
- Deze instructies importeren de tijd- en threadmodule die worden gebruikt om de uitvoering en vertraging van de Python-threads af te handelen.
- Hier heb je een functie gedefinieerd met de naam thread_test, die wordt aangeroepen door de start_new_thread methode. De functie voert een while-lus uit voor vier iteraties en drukt de naam af van de thread die deze heeft aangeroepen. Zodra de iteratie is voltooid, wordt een bericht afgedrukt dat de uitvoering van de thread is voltooid.
- Dit is het hoofdgedeelte van je programma. Hier roep je gewoon de start_new_thread . aan methode met de thread_test functie als een argument. Dit zal een nieuwe thread maken voor de functie die u als argument doorgeeft en deze beginnen uit te voeren. Merk op dat je dit kunt vervangen (thread_ test) met een andere functie die u als thread wilt gebruiken.
De inrijgmodule
Deze module is de implementatie op hoog niveau van threading in python en de de facto standaard voor het beheren van multithreaded-applicaties. Het biedt een breed scala aan functies in vergelijking met de threadmodule.
Hier is een lijst van enkele nuttige functies die in deze module zijn gedefinieerd:
Functienaam | Beschrijving |
---|---|
activeCount() | Retourneert het aantal Thread voorwerpen die nog leven |
currentThread() | Retourneert het huidige object van de Thread-klasse. |
enumerate() | Laat alle actieve Thread-objecten zien. |
isDaemon() | Retourneert true als de thread een daemon is. |
isAlive() | Retourneert true als de thread nog leeft. |
Thread Class-methoden | |
start() | Start de activiteit van een thread. Het moet slechts één keer worden aangeroepen voor elke thread, omdat het een runtime-fout zal geven als het meerdere keren wordt aangeroepen. |
run() | Deze methode geeft de activiteit van een thread aan en kan worden overschreven door een klasse die de klasse Thread uitbreidt. |
join() | Het blokkeert de uitvoering van andere code totdat de thread waarop de methode join() werd aangeroepen, wordt beëindigd. |
Achterverhaal:The Thread Class
Voordat u begint met het coderen van multithreaded-programma's met behulp van de threading-module, is het cruciaal om de Thread-klasse te begrijpen. De thread-klasse is de primaire klasse die de sjabloon en de bewerkingen van een thread in python definieert.
De meest gebruikelijke manier om een python-toepassing met meerdere threads te maken, is door een klasse te declareren die de klasse Thread uitbreidt en de methode run() overschrijft.
De klasse Thread, samengevat, betekent een codereeks die in een aparte thread wordt uitgevoerd van controle.
Dus als je een app met meerdere threads schrijft, doe je het volgende:
- definieer een klasse die de klasse Thread uitbreidt
- Overschrijf de __init__ constructeur
- Overschrijf de run() methode
Zodra een thread-object is gemaakt, wordt de start() methode kan worden gebruikt om de uitvoering van deze activiteit te starten en de join() methode kan worden gebruikt om alle andere code te blokkeren totdat de huidige activiteit is voltooid.
Laten we nu proberen de threading-module te gebruiken om uw vorige voorbeeld te implementeren. Start nogmaals uw IDLE en typ het volgende:
import time import threading class threadtester (threading.Thread): def __init__(self, id, name, i): threading.Thread.__init__(self) self.id = id self.name = name self.i = i def run(self): thread_test(self.name, self.i, 5) print ("%s has finished execution " %self.name) def thread_test(name, wait, i): while i: time.sleep(wait) print ("Running %s \n" %name) i = i - 1 if __name__=="__main__": thread1 = threadtester(1, "First Thread", 1) thread2 = threadtester(2, "Second Thread", 2) thread3 = threadtester(3, "Third Thread", 3) thread1.start() thread2.start() thread3.start() thread1.join() thread2.join() thread3.join()
Dit zal de output zijn wanneer je de bovenstaande code uitvoert:
CODE UITLEG
- Dit deel is hetzelfde als ons vorige voorbeeld. Hier importeert u de tijd- en threadmodule die worden gebruikt om de uitvoering en vertragingen van de Python-threads af te handelen.
- In dit deel maak je een klasse met de naam threadtester, die de Thread erft of uitbreidt klasse van de draadsnijmodule. Dit is een van de meest gebruikelijke manieren om threads in python te maken. U moet echter alleen de constructor en de run() . overschrijven methode in uw app. Zoals je kunt zien in het bovenstaande codevoorbeeld, is de __init__ methode (constructor) is overschreven. Op dezelfde manier heb je ook de run() . overschreven methode. Het bevat de code die u in een thread wilt uitvoeren. In dit voorbeeld heb je de functie thread_test() aangeroepen.
- Dit is de methode thread_test() die de waarde van i . aanneemt als een argument, verlaagt het met 1 bij elke iteratie en loopt door de rest van de code totdat i 0 wordt. In elke iteratie drukt het de naam af van de momenteel uitgevoerde thread en slaapt het voor seconden wachten (wat ook als een argument wordt beschouwd ).
- thread1 =threadtester(1, "First Thread", 1) Hier maken we een thread en geven we de drie parameters door die we in __init__ hebben gedeclareerd. De eerste parameter is de id van de thread, de tweede parameter is de naam van de thread en de derde parameter is de teller, die bepaalt hoe vaak de while-lus moet worden uitgevoerd.
- thread2.start()D e startmethode wordt gebruikt om de uitvoering van een thread te starten. Intern roept de start() functie de run() methode van je klasse aan.
- thread3.join() De methode join() blokkeert de uitvoering van andere code en wacht tot de thread waarop deze werd aangeroepen, is voltooid.
Zoals u al weet, hebben de threads die zich in hetzelfde proces bevinden, toegang tot het geheugen en de gegevens van dat proces. Als gevolg hiervan, als meer dan één thread tegelijkertijd probeert de gegevens te wijzigen of toegang te krijgen, kunnen er fouten binnensluipen.
In het volgende gedeelte ziet u de verschillende soorten complicaties die kunnen optreden wanneer threads toegang krijgen tot gegevens en kritieke secties zonder te controleren op bestaande toegangstransacties.
Deadlocks en racevoorwaarden
Voordat u leert over deadlocks en race-omstandigheden, is het handig om enkele basisdefinities met betrekking tot gelijktijdig programmeren te begrijpen:
- Kritische sectieHet is een codefragment dat toegang heeft tot gedeelde variabelen of deze wijzigt en moet worden uitgevoerd als een atomaire transactie.
- Contextomschakeling Het is het proces dat een CPU volgt om de status van een thread op te slaan voordat hij van de ene taak naar de andere gaat, zodat deze later vanaf hetzelfde punt kan worden hervat.
Pauzes
Deadlocks zijn het meest gevreesde probleem waarmee ontwikkelaars worden geconfronteerd bij het schrijven van gelijktijdige/multithreaded applicaties in Python. De beste manier om impasses te begrijpen is door het klassieke computerwetenschappelijke voorbeeldprobleem te gebruiken dat bekend staat als het Dining Philosophers Problem.
De probleemstelling voor eetfilosofen is als volgt:
Vijf filosofen zitten aan een ronde tafel met vijf borden spaghetti (een soort pasta) en vijf vorken, zoals in het schema te zien is.
Python
- free() Functie in C-bibliotheek:Hoe te gebruiken? Leer met voorbeeld
- Python String strip() Functie met VOORBEELD
- Python String count() met VOORBEELDEN
- Python round() functie met VOORBEELDEN
- Python map() functie met VOORBEELDEN
- Python Timeit() met voorbeelden
- Python-teller in verzamelingen met voorbeeld
- Python List count() met VOORBEELDEN
- Python Lijst index() met Voorbeeld
- C# - Multithreading
- Python - Programmeren met meerdere threads