I thread in Python

I thread sono la naturale evoluzione delle tecniche di fork/join viste in queste pagine. Come ampiamente trattato sui manuali, il thread non condivide tutto il codice del processo che lo genera e non c’è quindi la necessità di selezionare gli opportuni percorsi nel codice tra processi padre/figlio. Il thread è più snello anche da creare e gestire, seppur con limiti. Vediamo come in Python.

In python la gestione dei thread è molto semplice se affidata alle librerie di sistema. Vediamo un esempio banale di programma main che crea un thread e attende la sua conclusione. Il thread in questo caso non fa nulla, se non mettersi in pausa due secondi. A conti fatti il thread è un frammento di codice o meglio una funzione opportunamente invocata dal main.

import threading
import time

def mioThread(_numero):
    print("Thread " + str(_numero) + ": inizia \n")
    time.sleep(2)
    print("Thread " + str(_numero) + ": finisce \n")


if __name__ == "__main__":
    print("Main    : prima di creare il thread")
    x = threading.Thread(target=mioThread, args=(1,))
    print("Main    : dopo aver creato thread")
    x.start()
    print("Main    : attesa per la fine del thread")
    x.join()
    print("Main    : finito")

Se non ci sono intoppi, i messaggi dovrebbero essere stampati a video nell’ordine atteso. Ovviamente in questo caso la funzione eseguita come thread indipendente non ha grande valore computazionale.

Cosa possiamo notare nella realizzazione di questo frammento? Il thread, essendo una semplice funzione, non duplica l’intero codice del processo con un risparmio non di poco conto nella gestione dei percorsi binari con gli if/else da fare eseguire ai rispettivi fork e figli. Quindi il codice risulta più pulito da scrivere o leggere e da duplicare in memoria, ma ha ovviamente dei limiti nei passaggi di opportune variabili necessarie dal flusso principale a quello del thread (vedremo il concetto di thread safe più avanti) e in alcuni casi non è possibile semplificare un frammento di codice da eseguire in un thread di poche righe, piuttosto che con un fork. Dal punto di vista implementativo, esistono più modi per dichiarare ed eseguire un thread, anche gestendo delle intere classi che estendono quella di libreria. Per i nostri scopi didattici, ci accontentiamo di questa semplificazione in cui all’oggetto Thread, basta passare due parametri target e args, rispettivamente col nome della funzione e i parametri che prende in ingresso la funzione passata, nel nostro caso un parametro sciocco col numero progressivo del thread . Vedremo più avanti come recuperare i risultati dell’elaborazione nei diversi casi di concorrenza e parallelismo.

Nei prossimi post vedremo qualche esercizio per utilizzare in modo più realistico i nostri thread.

Ultima modifica 16 Gennaio 2022

Lascia un commento