logo

Wielowątkowość w Pythonie

W tym artykule omówiono podstawy wielowątkowości w języku programowania Python. Tak jak wieloprocesorowość , wielowątkowość to sposób na osiągnięcie wielozadaniowości. W wielowątkowości koncepcja wątki Jest używane. Najpierw zrozumiemy pojęcie nitka w architekturze komputerów.

Co to jest proces w Pythonie?

W informatyce A proces jest instancją programu komputerowego, który jest wykonywany. Każdy proces składa się z 3 podstawowych elementów:



  • Program wykonywalny.
  • Powiązane dane potrzebne programowi (zmienne, obszar roboczy, bufory itp.)
  • Kontekst wykonania programu (stan procesu)

Wprowadzenie do wątków w Pythonie

A nitka jest elementem procesu, który można zaplanować do wykonania. Jest to także najmniejsza jednostka przetwarzania, jaką można wykonać w systemie operacyjnym. Krótko mówiąc, wątek to sekwencja takich instrukcji w programie, która może zostać wykonana niezależnie od innego kodu. Dla uproszczenia można założyć, że wątek jest po prostu podzbiorem procesu! Wątek zawiera wszystkie te informacje w pliku Blok kontrolny wątku (TCB) :

  • Identyfikator wątku: Do każdego nowego wątku przypisywany jest unikalny identyfikator (TID).
  • Wskaźnik stosu: Wskazuje stos wątku w procesie. Stos zawiera zmienne lokalne w zakresie wątku.
  • Licznik programu: rejestr przechowujący adres instrukcji aktualnie wykonywanej przez wątek.
  • Stan wątku: może być uruchomiony, gotowy, czekać, uruchamiany lub gotowy.
  • Zestaw rejestrów wątku: rejestry przypisane do wątku do obliczeń.
  • Wskaźnik procesu nadrzędnego: Wskaźnik do bloku sterowania procesem (PCB) procesu, w którym działa wątek.

Rozważ poniższy diagram, aby zrozumieć związek pomiędzy procesem a jego wątkiem:

wielowątkowość-python-11

Związek między procesem a jego wątkiem



kiedy wynaleziono szkołę

W jednym procesie może istnieć wiele wątków, gdzie:

  • Każdy wątek zawiera swój własny zestaw rejestracyjny I zmienne lokalne (przechowywane na stosie) .
  • Wszystkie wątki procesu są współdzielone zmienne globalne (przechowywane na stercie) i kod programu .

Rozważ poniższy diagram, aby zrozumieć, w jaki sposób w pamięci istnieje wiele wątków:

wielowątkowość-python-21

Istnienie wielu wątków w pamięci



Wprowadzenie do wątków w Pythonie

Wielowątkowość definiuje się jako zdolność procesora do jednoczesnego wykonywania wielu wątków. W prostym, jednordzeniowym procesorze osiąga się to poprzez częste przełączanie pomiędzy wątkami. Nazywa się to przełączanie kontekstu . Podczas przełączania kontekstu stan wątku jest zapisywany, a stan innego wątku jest ładowany za każdym razem, gdy ma miejsce jakiekolwiek przerwanie (z powodu wejścia/wyjścia lub ustawienia ręcznego). Przełączanie kontekstu odbywa się tak często, że wydaje się, że wszystkie wątki działają równolegle (jest to tzw wielozadaniowość ).

Rozważmy poniższy diagram, na którym proces zawiera dwa aktywne wątki:

wielowątkowość-python-31

Wielowątkowość

Wielowątkowość w Pythonie

W Pyton , gwintowanie moduł zapewnia bardzo proste i intuicyjne API do tworzenia wielu wątków w programie. Spróbujmy krok po kroku zrozumieć kod wielowątkowy.

Krok 1: Moduł importu

Najpierw zaimportuj moduł wątków.

import threading>

Krok 2: Utwórz wątek

Aby utworzyć nowy wątek, tworzymy obiekt typu Nitka klasa. Jako parametry przyjmuje „cel” i „args”. The cel jest funkcją, która ma zostać wykonana przez wątek, podczas gdy argumenty są argumenty, które mają zostać przekazane do funkcji docelowej.

zmień nazwę w katalogu Linux
t1 = threading.Thread(target, args) t2 = threading.Thread(target, args)>

Krok 3: Rozpocznij wątek

Aby rozpocząć wątek, używamy początek() metoda klasy Thread.

t1.start() t2.start()>

Krok 4: Zakończ wykonanie wątku

Po uruchomieniu wątków bieżący program (można o nim myśleć jak o wątku głównym) również kontynuuje wykonywanie. Aby zatrzymać wykonywanie bieżącego programu do czasu zakończenia wątku, używamy metody dołączyć() metoda.

t1.join() t2.join()>

W rezultacie bieżący program będzie najpierw czekał na zakończenie t1 i wtedy t2 . Po ich zakończeniu wykonywane są pozostałe instrukcje bieżącego programu.

Przykład:

Rozważmy prosty przykład użycia modułu wątków.

Ten kod demonstruje, jak używać modułu wątków Pythona do jednoczesnego obliczania kwadratu i sześcianu liczby. Dwa wątki, t1> I t2> , są tworzone w celu wykonywania tych obliczeń. Są one uruchamiane, a ich wyniki są drukowane równolegle, zanim program wydrukuje Gotowe! gdy oba wątki się zakończą. Wątkowanie służy do osiągnięcia równoległości i poprawy wydajności programu podczas wykonywania zadań wymagających dużej mocy obliczeniowej.

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

>

>

Wyjście:

Square: 100 Cube: 1000 Done!>

Rozważ poniższy diagram, aby lepiej zrozumieć działanie powyższego programu:

wielowątkowość-python-4

Wielowątkowość

Przykład:

W tym przykładzie używamy os.getpid() funkcja, aby uzyskać identyfikator bieżącego procesu. Używamy wątek.main_thread() funkcja, aby uzyskać główny obiekt wątku. W normalnych warunkach wątkiem głównym jest wątek, z którego został uruchomiony interpreter Pythona. nazwa atrybut obiektu wątku służy do uzyskania nazwy wątku. Następnie używamy Threading.current_thread() funkcja, aby uzyskać bieżący obiekt wątku.

Rozważmy program w Pythonie podany poniżej, w którym wypisujemy nazwę wątku i odpowiadający mu proces dla każdego zadania.

przykład mapy Java

Ten kod demonstruje, jak używać modułu wątków Pythona do jednoczesnego wykonywania dwóch zadań. Program główny inicjuje dwa wątki, t1> I t2> , z których każdy jest odpowiedzialny za wykonanie określonego zadania. Wątki działają równolegle, a kod zawiera informacje o identyfikatorze procesu i nazwach wątków. Theos>moduł służy do uzyskiwania dostępu do identyfikatora procesu, a ' threading'> moduł służy do zarządzania wątkami i ich wykonywaniem.

Python3

Konwersja ciągu Java na liczbę całkowitą




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

>

>

Wyjście:

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>

Poniższy diagram wyjaśnia powyższą koncepcję:

wielowątkowość-python-5

Wielowątkowość

To było krótkie wprowadzenie do wielowątkowości w Pythonie. Następny artykuł z tej serii dotyczy synchronizacja pomiędzy wieloma wątkami . Wielowątkowość w Pythonie | Zestaw 2 (synchronizacja)

Pula wątków Pythona

Pula wątków to zbiór wątków tworzonych wcześniej i można ich ponownie używać do wykonywania wielu zadań. Moduł concurrent.futures w Pythonie udostępnia klasę ThreadPoolExecutor, która ułatwia tworzenie puli wątków i zarządzanie nią.

W tym przykładzie definiujemy proces roboczy funkcji, który będzie uruchamiany w wątku. Tworzymy ThreadPoolExecutor z maksymalnie 2 wątkami roboczymi. Następnie przesyłamy dwa zadania do puli za pomocą metody przesyłania. Pula zarządza wykonywaniem zadań w swoich wątkach roboczych. Używamy metody zamykania, aby poczekać na zakończenie wszystkich zadań, zanim główny wątek będzie kontynuowany.

Wielowątkowość może pomóc w zwiększeniu wydajności i responsywności programów. Jednak ważne jest, aby zachować ostrożność podczas pracy z wątkami, aby uniknąć problemów, takich jak warunki wyścigowe i zakleszczenia.

Ten kod wykorzystuje pulę wątków utworzoną za pomocą concurrent.futures.ThreadPoolExecutor> do jednoczesnego wykonywania dwóch zadań roboczych. Główny wątek czeka, aż wątki robocze zakończą pracę pool.shutdown(wait=True)> . Pozwala to na wydajne równoległe przetwarzanie zadań w środowisku wielowątkowym.

Python3




postać normalna Greibacha
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'>)>

>

>

Wyjście

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