Rust: concorrenza

Nella programmazione simultanea, diverse parti di un programma vengono eseguite in modo indipendente. D'altra parte, nella programmazione parallela, diverse parti di un programma vengono eseguite contemporaneamente. Entrambi i modelli sono ugualmente importanti in quanto più computer sfruttano i loro processori multipli.

Discussioni

Possiamo usare i thread per eseguire codici contemporaneamente. Nei sistemi operativi attuali, il codice di un programma eseguito viene eseguito in un processo e il sistema operativo gestisce più processi contemporaneamente. All'interno del tuo programma, puoi anche avere parti indipendenti che vengono eseguite simultaneamente. Le funzionalità che eseguono queste parti indipendenti sono chiamate thread.

Creazione di un thread

Il thread::spawnviene utilizzata per creare un nuovo thread. La funzione spawn accetta una chiusura come parametro. La chiusura definisce il codice che dovrebbe essere eseguito dal thread. L'esempio seguente stampa del testo da un thread principale e altro testo da un nuovo thread.

//import the necessary modules
use std::thread;
use std::time::Duration;

fn main() {
   //create a new thread
   thread::spawn(|| {
      for i in 1..10 {
         println!("hi number {} from the spawned thread!", i);
         thread::sleep(Duration::from_millis(1));
      }
   });
   //code executed by the main thread
   for i in 1..5 {
      println!("hi number {} from the main thread!", i);
      thread::sleep(Duration::from_millis(1));
   }
}

Produzione

hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the main thread!
hi number 2 from the spawned thread!
hi number 3 from the main thread!
hi number 3 from the spawned thread!
hi number 4 from the spawned thread!
hi number 4 from the main thread!

Il thread principale stampa i valori da 1 a 4.

NOTE- Il nuovo thread verrà interrotto quando termina il thread principale. L'output di questo programma potrebbe essere leggermente diverso ogni volta.

Il thread::sleepfunzione forza un thread a interrompere la sua esecuzione per un breve periodo, consentendo l'esecuzione di un thread diverso. I thread probabilmente si alterneranno, ma ciò non è garantito: dipende da come il sistema operativo pianifica i thread. In questa esecuzione, il thread principale viene stampato per primo, anche se l'istruzione print dal thread generato viene visualizzata per prima nel codice. Inoltre, anche se il thread generato è programmato per stampare valori fino a 9, è arrivato solo a 5 prima che il thread principale si spenga.

Unisci le maniglie

Un thread generato potrebbe non avere la possibilità di essere eseguito o eseguito completamente. Questo perché il thread principale si completa rapidamente. La funzione spawn <F, T> (f: F) -> JoinHandlelt; T> restituisce un JoinHandle. Il metodo join () su JoinHandle attende che il thread associato finisca.

use std::thread;
use std::time::Duration;

fn main() {
   let handle = thread::spawn(|| {
      for i in 1..10 {
         println!("hi number {} from the spawned thread!", i);
         thread::sleep(Duration::from_millis(1));
      }
   });
   for i in 1..5 {
      println!("hi number {} from the main thread!", i);
      thread::sleep(Duration::from_millis(1));
   }
   handle.join().unwrap();
}

Produzione

hi number 1 from the main thread!
hi number 1 from the spawned thread!
hi number 2 from the spawned thread!
hi number 2 from the main thread!
hi number 3 from the spawned thread!
hi number 3 from the main thread!
hi number 4 from the main thread!
hi number 4 from the spawned thread!
hi number 5 from the spawned thread!
hi number 6 from the spawned thread!
hi number 7 from the spawned thread!
hi number 8 from the spawned thread!
hi number 9 from the spawned thread!

Il thread principale e il thread generato continuano a passare.

NOTE - Il thread principale attende il completamento del thread generato a causa della chiamata a join() metodo.