logo

Multithreading in Python

Dit artikel behandelt de basisprincipes van multithreading in de programmeertaal Python. Net als multiverwerking is multithreading een manier om multitasking te bereiken. Bij multithreading is het concept van draden is gebruikt. Laten we eerst het concept van begrijpen draad op het gebied van computerarchitectuur.

Wat is een proces in Python?

Bij computergebruik is a proces is een exemplaar van een computerprogramma dat wordt uitgevoerd. Elk proces heeft 3 basiscomponenten:



  • Een uitvoerbaar programma.
  • De bijbehorende gegevens die het programma nodig heeft (variabelen, werkruimte, buffers, enz.)
  • De uitvoeringscontext van het programma (State of the process)

Een inleiding tot Python-threading

A draad is een entiteit binnen een proces dat kan worden gepland voor uitvoering. Het is bovendien de kleinste verwerkingseenheid die in een besturingssysteem (besturingssysteem) kan worden uitgevoerd. Simpel gezegd is een thread een reeks van dergelijke instructies binnen een programma die onafhankelijk van andere code kan worden uitgevoerd. Voor de eenvoud kun je ervan uitgaan dat een thread eenvoudigweg een subset van een proces is! Een thread bevat al deze informatie in een Draadcontroleblok (TCB) :

  • Onderwerpidentificatie: Aan elke nieuwe thread wordt een unieke ID (TID) toegewezen
  • Stapelwijzer: Wijst daarbij naar de stapel van de thread. De stapel bevat de lokale variabelen onder het bereik van de thread.
  • Programmateller: een register dat het adres opslaat van de instructie die momenteel door een thread wordt uitgevoerd.
  • Onderwerpstatus: kan actief zijn, klaar, wachtend, startend of klaar.
  • Thread's registerset: registers toegewezen aan thread voor berekeningen.
  • Bovenliggende procesaanwijzer: Een verwijzing naar het procescontroleblok (PCB) van het proces waar de draad op leeft.

Bekijk het onderstaande diagram om de relatie tussen het proces en de thread te begrijpen:

multithreading-python-11

Relatie tussen een proces en zijn draad



vos versus wolf

Binnen één proces kunnen meerdere threads bestaan ​​waarbij:

  • Elke draad bevat zijn eigen draad register ingesteld En lokale variabelen (opgeslagen in de stapel) .
  • Alle threads van een proces delen globale variabelen (opgeslagen in heap) en de programmacode .

Bekijk het onderstaande diagram om te begrijpen hoe er meerdere threads in het geheugen bestaan:

multithreading-python-21

Aanwezigheid van meerdere threads in het geheugen



Een inleiding tot threaden in Python

Multithreading wordt gedefinieerd als het vermogen van een processor om meerdere threads gelijktijdig uit te voeren. In een eenvoudige, single-core CPU wordt dit bereikt door regelmatig tussen threads te schakelen. Dit wordt genoemd contextwisseling . Bij contextwisseling wordt de status van een thread opgeslagen en wordt de status van een andere thread geladen wanneer er een interrupt plaatsvindt (als gevolg van I/O of handmatig ingesteld). Het wisselen van context vindt zo vaak plaats dat het lijkt alsof alle threads parallel lopen (dit wordt genoemd multitasking ).

Beschouw het onderstaande diagram waarin een proces twee actieve threads bevat:

multithreading-python-31

Multithreading

Multithreading in Python

In Python , de draadsnijden module biedt een zeer eenvoudige en intuïtieve API voor het genereren van meerdere threads in een programma. Laten we proberen multithreading-code stap voor stap te begrijpen.

Stap 1: Importmodule

Importeer eerst de draadsnijmodule.

import threading>

Stap 2: Maak een draad

Om een ​​nieuwe thread te maken, maken we een object van de Draad klas. Het neemt de ‘target’ en ‘args’ als parameters. De doel is de functie die door de thread moet worden uitgevoerd, terwijl de args is de argumenten die aan de doelfunctie moeten worden doorgegeven.

t1 = threading.Thread(target, args) t2 = threading.Thread(target, args)>

Stap 3: Start een draad

Om een ​​draad te starten, gebruiken we de begin() methode van de klasse Thread.

t1.start() t2.start()>

Stap 4: Beëindig de draad Uitvoering

Zodra de threads starten, blijft het huidige programma (je kunt het zien als een hoofdthread) ook doorgaan met uitvoeren. Om de uitvoering van het huidige programma te stoppen totdat een thread voltooid is, gebruiken we de meedoen() methode.

t1.join() t2.join()>

Hierdoor wacht het huidige programma eerst op de voltooiing van t1 en dan t2 . Zodra ze klaar zijn, worden de resterende instructies van het huidige programma uitgevoerd.

Voorbeeld:

Laten we een eenvoudig voorbeeld bekijken waarbij we een draadsnijmodule gebruiken.

Deze code laat zien hoe je de threading-module van Python kunt gebruiken om tegelijkertijd het kwadraat en de derde macht van een getal te berekenen. Twee draden, t1> En t2> , zijn gemaakt om deze berekeningen uit te voeren. Ze worden gestart en hun resultaten worden parallel afgedrukt voordat het programma Klaar! wanneer beide threads klaar zijn. Threading wordt gebruikt om parallellisme te bereiken en de programmaprestaties te verbeteren bij het omgaan met rekenintensieve taken.

Python3




import> threading> def> print_cube(num):> >print>(>'Cube: {}'> .>format>(num>*> num>*> num))> def> print_square(num):> >print>(>'Square: {}'> .>format>(num>*> num))> if> __name__>=>=>'__main__'>:> >t1>=> threading.Thread(target>=>print_square, args>=>(>10>,))> >t2>=> threading.Thread(target>=>print_cube, args>=>(>10>,))> >t1.start()> >t2.start()> >t1.join()> >t2.join()> >print>(>'Done!'>)>

>

>

Uitgang:

Square: 100 Cube: 1000 Done!>

Bekijk het onderstaande diagram voor een beter begrip van hoe het bovenstaande programma werkt:

multithreading-python-4

Multithreading

Voorbeeld:

In dit voorbeeld gebruiken we os.getpid() functie om de ID van het huidige proces op te halen. We gebruiken threading.main_thread() functie om het hoofdthreadobject op te halen. Onder normale omstandigheden is de hoofdthread de thread van waaruit de Python-interpreter is gestart. naam attribuut van het thread-object wordt gebruikt om de naam van de thread op te halen. Dan gebruiken wij de threading.current_thread() functie om het huidige threadobject op te halen.

Beschouw het onderstaande Python-programma waarin we de threadnaam en het bijbehorende proces voor elke taak afdrukken.

Deze code laat zien hoe je de threading-module van Python kunt gebruiken om twee taken gelijktijdig uit te voeren. Het hoofdprogramma initieert twee threads, t1> En t2> , elk verantwoordelijk voor het uitvoeren van een specifieke taak. De threads lopen parallel en de code biedt informatie over de proces-ID en threadnamen. Deos>module wordt gebruikt om toegang te krijgen tot de proces-ID, en de ' threading'> module wordt gebruikt om threads en hun uitvoering te beheren.

Python3


Java-klassediagram



import> threading> import> os> def> task1():> >print>(>'Task 1 assigned to thread: {}'>.>format>(threading.current_thread().name))> >print>(>'ID of process running task 1: {}'>.>format>(os.getpid()))> def> task2():> >print>(>'Task 2 assigned to thread: {}'>.>format>(threading.current_thread().name))> >print>(>'ID of process running task 2: {}'>.>format>(os.getpid()))> if> __name__>=>=> '__main__'>:> >print>(>'ID of process running main program: {}'>.>format>(os.getpid()))> >print>(>'Main thread name: {}'>.>format>(threading.current_thread().name))> >t1>=> threading.Thread(target>=>task1, name>=>'t1'>)> >t2>=> threading.Thread(target>=>task2, name>=>'t2'>)> >t1.start()> >t2.start()> >t1.join()> >t2.join()>

>

>

Uitgang:

ID of process running main program: 1141 Main thread name: MainThread Task 1 assigned to thread: t1 ID of process running task 1: 1141 Task 2 assigned to thread: t2 ID of process running task 2: 1141>

Het onderstaande diagram maakt het bovenstaande concept duidelijk:

multithreading-python-5

Multithreading

Dit was dus een korte introductie tot multithreading in Python. Het volgende artikel in deze serie gaat over synchronisatie tussen meerdere threads . Multithreading in Python | Set 2 (Synchronisatie)

welke maanden bevinden zich in q3

Python ThreadPool

Een threadpool is een verzameling threads die vooraf zijn gemaakt en die opnieuw kunnen worden gebruikt om meerdere taken uit te voeren. De concurrent.futures-module in Python biedt een ThreadPoolExecutor-klasse waarmee u eenvoudig een threadpool kunt maken en beheren.

In dit voorbeeld definiëren we een functiewerker die in een thread wordt uitgevoerd. We maken een ThreadPoolExecutor met maximaal 2 werkthreads. Vervolgens dienen we twee taken in bij de pool met behulp van de verzendmethode. De pool beheert de uitvoering van de taken in de werkthreads. We gebruiken de afsluitmethode om te wachten tot alle taken zijn voltooid voordat de hoofdthread verdergaat.

Multithreading kan u helpen uw programma's efficiënter en responsiever te maken. Het is echter belangrijk om voorzichtig te zijn bij het werken met threads om problemen zoals raceomstandigheden en impasses te voorkomen.

Deze code maakt gebruik van een threadpool die is gemaakt met concurrent.futures.ThreadPoolExecutor> om twee werktaken tegelijkertijd uit te voeren. De hoofdthread wacht tot de werkthreads klaar zijn met gebruiken pool.shutdown(wait=True)> . Dit maakt een efficiënte parallelle verwerking van taken in een multi-threaded omgeving mogelijk.

Python3




import> concurrent.futures> def> worker():> >print>(>'Worker thread running'>)> pool>=> concurrent.futures.ThreadPoolExecutor(max_workers>=>2>)> pool.submit(worker)> pool.submit(worker)> pool.shutdown(wait>=>True>)> print>(>'Main thread continuing to run'>)>

>

>

Uitvoer

Worker thread running Worker thread running Main thread continuing to run>