Concorrenza in Python - Introduzione

In questo capitolo, capiremo il concetto di concorrenza in Python e impareremo i diversi thread e processi.

Cos'è la concorrenza?

In parole semplici, la concorrenza è il verificarsi di due o più eventi contemporaneamente. La concorrenza è un fenomeno naturale perché molti eventi si verificano contemporaneamente in un dato momento.

In termini di programmazione, la concorrenza è quando due attività si sovrappongono durante l'esecuzione. Con la programmazione simultanea, le prestazioni delle nostre applicazioni e dei nostri sistemi software possono essere migliorate perché possiamo gestire contemporaneamente le richieste piuttosto che attendere il completamento di una precedente.

Revisione storica della concorrenza

I punti seguenti ci forniranno una breve rassegna storica della concorrenza:

Dal concetto di ferrovia

La concorrenza è strettamente correlata al concetto di ferrovia. Con le ferrovie, c'era la necessità di gestire più treni sullo stesso sistema ferroviario in modo tale che ogni treno arrivasse a destinazione in sicurezza.

Calcolo concorrente nel mondo accademico

L'interesse per la concorrenza informatica è iniziato con il documento di ricerca pubblicato da Edsger W. Dijkstra nel 1965. In questo articolo, ha identificato e risolto il problema dell'esclusione reciproca, la proprietà del controllo della concorrenza.

Primitive di concorrenza di alto livello

In tempi recenti, i programmatori stanno ottenendo soluzioni simultanee migliorate grazie all'introduzione di primitive di concorrenza di alto livello.

Concorrenza migliorata con i linguaggi di programmazione

Linguaggi di programmazione come Golang, Rust e Python di Google hanno realizzato incredibili sviluppi in aree che ci aiutano a ottenere migliori soluzioni simultanee.

Cosa sono thread e multithreading?

Threadè la più piccola unità di esecuzione che può essere eseguita in un sistema operativo. Non è di per sé un programma ma viene eseguito all'interno di un programma. In altre parole, i thread non sono indipendenti l'uno dall'altro. Ogni thread condivide la sezione del codice, la sezione dei dati, ecc. Con altri thread. Sono anche conosciuti come processi leggeri.

Un thread è costituito dai seguenti componenti:

  • Contatore di programma che consiste nell'indirizzo della successiva istruzione eseguibile

  • Stack

  • Set di registri

  • Un ID unico

Multithreading, d'altra parte, è la capacità di una CPU di gestire l'uso del sistema operativo eseguendo più thread contemporaneamente. L'idea principale del multithreading è ottenere il parallelismo dividendo un processo in più thread. Il concetto di multithreading può essere compreso con l'aiuto del seguente esempio.

Esempio

Supponiamo di eseguire un particolare processo in cui apriamo MS Word per digitare il contenuto al suo interno. Un thread verrà assegnato per aprire MS Word e un altro thread sarà richiesto per digitare il contenuto in esso. E ora, se vogliamo modificare l'esistente, sarà necessario un altro thread per eseguire l'attività di modifica e così via.

Che cos'è il processo e il multiprocessing?

UNprocessè definita come un'entità, che rappresenta l'unità di lavoro di base da implementare nel sistema. Per dirla in termini semplici, scriviamo i nostri programmi per computer in un file di testo e quando eseguiamo questo programma, diventa un processo che esegue tutte le attività menzionate nel programma. Durante il ciclo di vita del processo, passa attraverso diverse fasi: avvio, pronto, funzionamento, attesa e termine.

Il diagramma seguente mostra le diverse fasi di un processo:

Un processo può avere un solo thread, chiamato thread primario, o più thread con il proprio insieme di registri, contatore di programma e stack. Il diagramma seguente ci mostrerà la differenza:

Multiprocessing,d'altra parte, è l'uso di due o più unità CPU all'interno di un singolo sistema di computer. Il nostro obiettivo principale è ottenere il pieno potenziale dal nostro hardware. Per ottenere ciò, dobbiamo utilizzare il numero completo di core della CPU disponibili nel nostro sistema informatico. Il multiprocessing è l'approccio migliore per farlo.

Python è uno dei linguaggi di programmazione più popolari. Di seguito sono riportati alcuni motivi che lo rendono adatto per applicazioni simultanee:

Zucchero sintattico

Lo zucchero sintattico è la sintassi all'interno di un linguaggio di programmazione progettato per rendere le cose più facili da leggere o da esprimere. Rende il linguaggio "più dolce" per l'uso umano: le cose possono essere espresse in modo più chiaro, più conciso o in uno stile alternativo basato sulle preferenze. Python viene fornito con metodi Magic, che possono essere definiti per agire sugli oggetti. Questi metodi Magic sono usati come zucchero sintattico e legati a parole chiave più facili da capire.

Grande comunità

Il linguaggio Python ha assistito a un enorme tasso di adozione tra data scientist e matematici, che lavorano nel campo dell'IA, dell'apprendimento automatico, del deep learning e dell'analisi quantitativa.

API utili per la programmazione concorrente

Python 2 e 3 hanno un gran numero di API dedicate per la programmazione parallela / concorrente. I più popolari sonothreading, concurrent.features, multiprocessing, asyncio, gevent and greenlets, eccetera.

Limitazioni di Python nell'implementazione di applicazioni concorrenti

Python ha una limitazione per le applicazioni simultanee. Questa limitazione è chiamataGIL (Global Interpreter Lock)è presente in Python. GIL non ci consente mai di utilizzare più core della CPU e quindi possiamo dire che non ci sono veri thread in Python. Possiamo comprendere il concetto di GIL come segue:

GIL (Global Interpreter Lock)

È uno degli argomenti più controversi nel mondo Python. In CPython, GIL è il mutex, il blocco di mutua esclusione, che rende le cose thread-safe. In altre parole, possiamo dire che GIL impedisce a più thread di eseguire codice Python in parallelo. Il blocco può essere mantenuto da un solo thread alla volta e se si desidera eseguire un thread, è necessario prima acquisire il blocco. Il diagramma mostrato di seguito ti aiuterà a capire il funzionamento di GIL.

Tuttavia, ci sono alcune librerie e implementazioni in Python come Numpy, Jpython e IronPytbhon. Queste librerie funzionano senza alcuna interazione con GIL.