Python Threading: An Introduction – tipsbilk.net

I denne opplæringen lærer du hvordan du bruker Pythons innebygde trådingsmodul for å utforske multithreading-funksjoner i Python.

Fra og med det grunnleggende om prosesser og tråder, vil du lære hvordan multithreading fungerer i Python – mens du forstår begrepene samtidighet og parallellitet. Du vil da lære hvordan du starter og kjører en eller flere tråder i Python ved å bruke den innebygde trådingsmodulen.

La oss komme i gang.

Prosesser vs. tråder: Hva er forskjellene?

Hva er en prosess?

En prosess er enhver forekomst av et program som må kjøres.

Det kan være hva som helst – et Python-skript eller en nettleser som Chrome til en videokonferanseapplikasjon. Hvis du starter Task Manager på maskinen din og navigerer til Ytelse –> CPU, vil du kunne se prosessene og trådene som kjører på CPU-kjernene dine.

Forstå prosesser og tråder

Internt har en prosess et dedikert minne som lagrer koden og dataene som tilsvarer prosessen.

En prosess består av en eller flere tråder. En tråd er den minste sekvensen av instruksjoner som operativsystemet kan utføre, og den representerer flyten av utførelse.

Hver tråd har sin egen stabel og registre, men ikke et dedikert minne. Alle trådene knyttet til en prosess kan få tilgang til dataene. Derfor deles data og minne av alle trådene i en prosess.

I en CPU med N kjerner kan N prosesser utføres parallelt på samme tidspunkt. Imidlertid kan to tråder av samme prosess aldri kjøres parallelt – men kan kjøres samtidig. Vi vil ta opp begrepet samtidighet vs. parallellisme i neste avsnitt.

Basert på det vi har lært så langt, la oss oppsummere forskjellene mellom en prosess og en tråd.

FeatureProcessThreadMemoryDedikert minne Delt minne UtførelsesmodusParallell, samtidigSamtidig; men ikke parallelExecution håndtert av Operating SystemCPython Interpreter

Multithreading i Python

I Python sikrer Global Interpreter Lock (GIL) at bare én tråd kan skaffe låsen og kjøre til enhver tid. Alle tråder bør få denne låsen for å kjøre. Dette sikrer at bare en enkelt tråd kan kjøres – på et gitt tidspunkt – og unngår samtidig multithreading.

  Hvordan endre fargetemaet til Microsoft Office

Tenk for eksempel på to tråder, t1 og t2, av samme prosess. Fordi tråder deler samme data når t1 leser en bestemt verdi k, kan t2 endre den samme verdien k. Dette kan føre til vranglås og uønskede resultater. Men bare én av trådene kan skaffe seg låsen og kjøre når som helst. Derfor sørger GIL også for gjengesikkerhet.

Så hvordan oppnår vi multithreading-funksjoner i Python? For å forstå dette, la oss diskutere begrepene samtidighet og parallellisme.

Samtidighet vs. parallellisme: en oversikt

Tenk på en CPU med mer enn én kjerne. I illustrasjonen nedenfor har CPU-en fire kjerner. Dette betyr at vi kan ha fire forskjellige operasjoner som kjører parallelt til enhver tid.

Hvis det er fire prosesser, kan hver av prosessene kjøre uavhengig og samtidig på hver av de fire kjernene. La oss anta at hver prosess har to tråder.

For å forstå hvordan tråding fungerer, la oss bytte fra flerkjerne- til enkeltkjerneprosessorarkitektur. Som nevnt kan bare en enkelt tråd være aktiv ved en bestemt utførelsesforekomst; men prosessorkjernen kan bytte mellom trådene.

For eksempel venter ofte I/O-bundne tråder på I/O-operasjoner: lesing av brukerinndata, databaselesing og filoperasjoner. I løpet av denne ventetiden kan den frigjøre låsen slik at den andre tråden kan løpe. Ventetiden kan også være en enkel operasjon som å sove i n sekunder.

Oppsummert: Under venteoperasjoner frigjør tråden låsen, slik at prosessorkjernen kan bytte til en annen tråd. Den tidligere tråden gjenopptas kjøringen etter at venteperioden er fullført. Denne prosessen, hvor prosessorkjernen bytter mellom trådene samtidig, letter multithreading. ✅

Hvis du ønsker å implementere parallellitet på prosessnivå i applikasjonen din, bør du vurdere å bruke multiprosessering i stedet.

Python Threading Module: Første trinn

Python leveres med en trådmodul som du kan importere til Python-skriptet.

import threading

For å lage et trådobjekt i Python kan du bruke trådkonstruktøren: threading.Thread(…). Dette er den generiske syntaksen som er tilstrekkelig for de fleste trådimplementeringer:

threading.Thread(target=...,args=...)

Her,

  • target er nøkkelordargumentet som angir en Python-kallbar
  • args er tuppelen av argumenter som målet tar inn.
  9 beste nettauksjonsprogramvare å bruke i 2022

Du trenger Python 3.x for å kjøre kodeeksemplene i denne opplæringen. Last ned koden og følg med.

Hvordan definere og kjøre tråder i Python

La oss definere en tråd som kjører en målfunksjon.

Målfunksjonen er some_func.

import threading
import time

def some_func():
    print("Running some_func...")
    time.sleep(2)
    print("Finished running some_func.")

thread1 = threading.Thread(target=some_func)
thread1.start()
print(threading.active_count())

La oss analysere hva kodebiten ovenfor gjør:

  • Den importerer tråden og tidsmodulene.
  • Funksjonen some_func har beskrivende print()-setninger og inkluderer en dvaleoperasjon i to sekunder: time.sleep(n) får funksjonen til å hvile i n sekunder.
  • Deretter definerer vi en tråd thread_1 med målet som some_func. threading.Thread(target=…) oppretter et trådobjekt.
  • Merk: Angi navnet på funksjonen og ikke et funksjonskall; bruk some_func og ikke some_func().
  • Å lage et trådobjekt starter ikke en tråd; kaller start()-metoden på trådobjektet gjør det.
  • For å få antall aktive tråder bruker vi active_count() funksjonen.

Python-skriptet kjører på hovedtråden, og vi lager en annen tråd (thread1) for å kjøre funksjonen some_func slik at det aktive trådantallet er to, som vist i utdata:

# Output
Running some_func...
2
Finished running some_func.

Hvis vi ser nærmere på utdataene, ser vi at når tråd1 startes, kjører den første utskriftssetningen. Men under hvilemodus bytter prosessoren til hovedtråden og skriver ut antall aktive tråder – uten å vente på at tråd1 skal fullføres.

Venter på at trådene skal fullføres

Hvis du vil at tråd1 skal fullføre utførelsen, kan du kalle join()-metoden på den etter å ha startet tråden. Hvis du gjør det, venter du på at tråd1 fullfører utførelse uten å bytte til hovedtråden.

import threading
import time

def some_func():
    print("Running some_func...")
    time.sleep(2)
    print("Finished running some_func.")

thread1 = threading.Thread(target=some_func)
thread1.start()
thread1.join()
print(threading.active_count())

Nå er tråd1 ferdig utført før vi skriver ut det aktive trådantallet. Så bare hovedtråden kjører, noe som betyr at antallet aktive tråder er én. ✅

# Output
Running some_func...
Finished running some_func.
1

Hvordan kjøre flere tråder i Python

La oss deretter lage to tråder for å kjøre to forskjellige funksjoner.

Her er count_down en funksjon som tar inn et tall som argument og teller ned fra det tallet til null.

def count_down(n):
    for i in range(n,-1,-1):
        print(i)

Vi definerer count_up, en annen Python-funksjon som teller fra null opp til et gitt tall.

def count_up(n):
    for i in range(n+1):
        print(i)

📑 Når du bruker funksjonen range() med syntaksområdet (start, stopp, trinn), ekskluderes sluttpunktstoppet som standard.

  TruthFinder gratis prøveversjon, tilbudets varighet og pris

– For å telle ned fra et bestemt tall til null, kan du bruke en negativ trinnverdi på -1 og sette stoppverdien til -1 slik at null er inkludert.

– På samme måte, for å telle opp til n, må du sette stoppverdien til n + 1. Fordi standardverdiene for start og trinn er henholdsvis 0 og 1, kan du bruke range(n + 1) for å få sekvensen 0 gjennom n.

Deretter definerer vi to tråder, tråd1 og tråd2 for å kjøre funksjonene count_down og count_up, henholdsvis. Vi legger til utskriftserklæringer og dvaleoperasjoner for begge funksjonene.

Når du oppretter trådobjektene, legg merke til at argumentene til målfunksjonen skal spesifiseres som en tuppel – til parameteren args. Siden begge funksjonene (count_down og count_up) tar inn ett argument. Du må sette inn et komma eksplisitt etter verdien. Dette sikrer at argumentet fortsatt sendes inn som en tuppel, ettersom de påfølgende elementene utledes som Ingen.

import threading
import time

def count_down(n):
    for i in range(n,-1,-1):
        print("Running thread1....")
        print(i)
        time.sleep(1)


def count_up(n):
    for i in range(n+1):
        print("Running thread2...")
        print(i)
        time.sleep(1)

thread1 = threading.Thread(target=count_down,args=(10,))
thread2 = threading.Thread(target=count_up,args=(5,))
thread1.start()
thread2.start()

I utgangen:

  • Funksjonen count_up kjører på tråd2 og teller opp til 5 fra 0.
  • Nedtellingsfunksjonen kjører på tråd1 teller ned fra 10 til 0.
# Output
Running thread1....
10
Running thread2...
0
Running thread1....
9
Running thread2...
1
Running thread1....
8
Running thread2...
2
Running thread1....
7
Running thread2...
3
Running thread1....
6
Running thread2...
4
Running thread1....
5
Running thread2...
5
Running thread1....
4
Running thread1....
3
Running thread1....
2
Running thread1....
1
Running thread1....
0

Du kan se at tråd1 og tråd2 kjøres vekselvis, siden begge involverer en venteoperasjon (søvn). Når count_up-funksjonen er ferdig med å telle opp til 5, er tråd2 ikke lenger aktiv. Så vi får utgangen som tilsvarer bare tråd1.

Oppsummering

I denne opplæringen har du lært hvordan du bruker Pythons innebygde trådmodul for å implementere multithreading. Her er et sammendrag av de viktigste takeawayene:

  • Trådkonstruktøren kan brukes til å lage et trådobjekt. Ved å bruke threading.Thread(target=,args=()) opprettes en tråd som kjører målet callable med argumenter spesifisert i args.
  • Python-programmet kjører på en hovedtråd, så trådobjektene du lager er ekstra tråder. Du kan kalle active_count() funksjonen returnerer antall aktive tråder til enhver instans.
  • Du kan starte en tråd ved å bruke start()-metoden på trådobjektet og vente til den er ferdig utført med join()-metoden.

Du kan kode flere eksempler ved å justere ventetidene, prøve en annen I/O-operasjon og mer. Sørg for å implementere multithreading i dine kommende Python-prosjekter. Lykke til med koding!🎉