logo

Multithreading în Python

Acest articol acoperă elementele de bază ale multithreadingului în limbajul de programare Python. Exact ca multiprocesare , multithreading-ul este o modalitate de a realiza multitasking. În multithreading, conceptul de fire este folosit. Să înțelegem mai întâi conceptul de fir în arhitectura calculatoarelor.

Ce este un proces în Python?

În calcul, a proces este o instanță a unui program de calculator care se execută. Orice proces are 3 componente de bază:



  • Un program executabil.
  • Datele asociate necesare programului (variabile, spațiu de lucru, buffere etc.)
  • Contextul de execuție al programului (Starea procesului)

O introducere în Python Threading

A fir este o entitate dintr-un proces care poate fi programată pentru execuție. De asemenea, este cea mai mică unitate de procesare care poate fi efectuată într-un OS (Sistem de Operare). Cu cuvinte simple, un fir este o secvență de astfel de instrucțiuni în cadrul unui program care poate fi executată independent de alt cod. Pentru simplitate, puteți presupune că un fir este pur și simplu un subset al unui proces! Un thread conține toate aceste informații într-un Bloc de control al firului (TCB) :

  • Identificator de fir: ID unic (TID) este atribuit fiecărui fir nou
  • Indicator de stivă: Indică stiva firului în proces. Stiva conține variabilele locale din domeniul de aplicare al firului.
  • Contor de programe: un registru care stochează adresa instrucțiunii în curs de executare de către un fir.
  • Stare fir: poate fi în funcțiune, gata, în așteptare, pornire sau gata.
  • Set de registru pentru fir: registrele alocate firului pentru calcule.
  • Pointer proces părinte: Un pointer către blocul de control al procesului (PCB) al procesului în care trăiește firul.

Luați în considerare diagrama de mai jos pentru a înțelege relația dintre proces și firul său:

multithreading-python-11

Relația dintre un proces și firul său



Pot exista mai multe fire într-un singur proces în care:

arbore binar vs arbore binar de căutare
  • Fiecare fir contine al lui set de registre și variabile locale (stocate în stivă) .
  • Toate firele unui proces partajează variabile globale (stocate în heap) si codul programului .

Luați în considerare diagrama de mai jos pentru a înțelege cum există mai multe fire de execuție în memorie:

multithreading-python-21

Existența mai multor fire în memorie



O introducere în Threading în Python

Multithreading este definită ca capacitatea unui procesor de a executa mai multe fire simultan. Într-un procesor simplu, cu un singur nucleu, se realizează folosind comutarea frecventă între fire. Aceasta se numește schimbarea contextului . În schimbarea contextului, starea unui thread este salvată și starea unui alt thread este încărcată ori de câte ori are loc orice întrerupere (datorită I/O sau setată manual). Comutarea contextului are loc atât de frecvent încât toate firele de execuție par să ruleze în paralel (acesta se numește multifunctional ).

Luați în considerare diagrama de mai jos în care un proces conține două fire active:

multithreading-python-31

Multithreading

Multithreading în Python

În Piton , cel filetat modulul oferă un API foarte simplu și intuitiv pentru generarea mai multor fire într-un program. Să încercăm să înțelegem codul multithreading pas cu pas.

Pasul 1: Modul de import

Mai întâi, importați modulul de filetare.

import threading>

Pasul 2: Creați un thread

Pentru a crea un fir nou, creăm un obiect al Fir clasă. Ia „țintă” și „args” ca parametri. The ţintă este funcția care urmează să fie executată de thread, în timp ce args este argumentele care urmează să fie transmise funcției țintă.

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

Pasul 3: Începeți un subiect

tabel de reacții

Pentru a începe un thread, folosim start() metoda clasei Thread.

t1.start() t2.start()>

Pasul 4: Încheiați execuția firului

Odată ce firele de execuție pornesc, programul curent (vă puteți gândi la el ca pe un fir principal) continuă să se execute. Pentru a opri execuția programului curent până când un fir este complet, folosim a te alatura() metodă.

t1.join() t2.join()>

Ca urmare, programul curent va aștepta mai întâi finalizarea t1 și apoi t2 . Odată ce acestea sunt terminate, instrucțiunile rămase din programul curent sunt executate.

Exemplu:

Să luăm în considerare un exemplu simplu folosind un modul de threading.

Acest cod demonstrează cum să utilizați modulul de threading al lui Python pentru a calcula simultan pătratul și cubul unui număr. Două fire, t1> și t2> , sunt create pentru a efectua aceste calcule. Acestea sunt pornite, iar rezultatele lor sunt tipărite în paralel înainte ca programul să fie tipărit Gata! când ambele fire s-au terminat. Threadingul este folosit pentru a obține paralelismul și pentru a îmbunătăți performanța programului atunci când se ocupă cu sarcini intensive din punct de vedere computațional.

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!'>)>

>

>

Ieșire:

Square: 100 Cube: 1000 Done!>

Luați în considerare diagrama de mai jos pentru o mai bună înțelegere a modului în care funcționează programul de mai sus:

multithreading-python-4

Multithreading

Exemplu:

În acest exemplu, folosim os.getpid() pentru a obține ID-ul procesului curent. Folosim threading.main_thread() funcția pentru a obține obiectul firului principal. În condiții normale, firul principal este firul de la care a fost pornit interpretul Python. Nume atributul obiectului thread este folosit pentru a obține numele firului. Apoi folosim threading.current_thread() funcția pentru a obține obiectul thread curent.

Luați în considerare programul Python prezentat mai jos în care tipărim numele firului și procesul corespunzător pentru fiecare sarcină.

Acest cod demonstrează cum să utilizați modulul de threading al lui Python pentru a rula două sarcini simultan. Programul principal inițiază două fire, t1> și t2> , fiecare responsabil pentru executarea unei sarcini specifice. Firele rulează în paralel, iar codul oferă informații despre ID-ul procesului și numele firelor. Theos>modulul este utilizat pentru a accesa ID-ul procesului și ' threading'> modulul este utilizat pentru a gestiona firele de execuție și execuția lor.

lumea wumpusului

Python3

conversia unui șir în întreg în java




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()>

>

>

Ieșire:

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>

Diagrama de mai jos clarifică conceptul de mai sus:

multithreading-python-5

Multithreading

Deci, aceasta a fost o scurtă introducere în multithreading în Python. Următorul articol din această serie acoperă sincronizare între mai multe fire . Multithreading în Python | Setul 2 (Sincronizare)

Python ThreadPool

Un pool de fire este o colecție de fire care sunt create în avans și pot fi reutilizate pentru a executa mai multe sarcini. Modulul concurrent.futures din Python oferă o clasă ThreadPoolExecutor care facilitează crearea și gestionarea unui pool de fire.

În acest exemplu, definim o funcție de lucru care va rula într-un fir. Creăm un ThreadPoolExecutor cu maximum 2 fire de lucru. Trimitem apoi două sarcini la grup folosind metoda de trimitere. Pool-ul gestionează execuția sarcinilor din firele sale de lucru. Folosim metoda de închidere pentru a aștepta finalizarea tuturor sarcinilor înainte ca firul principal să continue.

Multithreading vă poate ajuta să vă faceți programele mai eficiente și mai receptive. Cu toate acestea, este important să fiți atenți atunci când lucrați cu fire pentru a evita probleme precum condițiile de cursă și blocajele.

Acest cod folosește un pool de fire create cu concurrent.futures.ThreadPoolExecutor> pentru a rula simultan două sarcini de lucrător. Firul principal așteaptă ca firele de lucru să termine de utilizat pool.shutdown(wait=True)> . Acest lucru permite procesarea eficientă în paralel a sarcinilor într-un mediu cu mai multe fire.

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'>)>

blocați reclamele youtube Android

>

>

Ieșire

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