Qual è la differenza tra un filo e una fibra?


187

Qual è la differenza tra un filo e una fibra? Ho sentito parlare di fibre dal rubino e ho letto che sono disponibili in altre lingue, qualcuno potrebbe spiegarmi in termini semplici qual è la differenza tra un filo e una fibra.

Risposte:


163

In termini più semplici, i fili sono generalmente considerati preventivi (sebbene ciò non sia sempre vero, a seconda del sistema operativo) mentre le fibre sono considerate fili leggeri e cooperativi. Entrambi sono percorsi di esecuzione separati per l'applicazione.

Con thread: il percorso di esecuzione corrente può essere interrotto o preemptato in qualsiasi momento (nota: questa affermazione è una generalizzazione e potrebbe non essere sempre vera a seconda del sistema operativo / pacchetto di threading / ecc.). Ciò significa che per i thread, l'integrità dei dati è un grosso problema perché un thread può essere interrotto durante l'aggiornamento di un blocco di dati, lasciando l'integrità dei dati in uno stato errato o incompleto. Ciò significa anche che il sistema operativo può sfruttare più CPU e core della CPU eseguendo più di un thread contemporaneamente e lasciando allo sviluppatore la protezione dell'accesso ai dati.

Con le fibre: l'attuale percorso di esecuzione viene interrotto solo quando la fibra dà esecuzione (stessa nota di cui sopra). Ciò significa che le fibre si avviano e si fermano sempre in luoghi ben definiti, quindi l'integrità dei dati è molto meno problematica. Inoltre, poiché le fibre sono spesso gestite nello spazio utente, non è necessario apportare costosi cambi di contesto e modifiche dello stato della CPU, rendendo estremamente efficiente il passaggio da una fibra a quella successiva. D'altra parte, poiché non è possibile far funzionare due fibre esattamente contemporaneamente, il solo utilizzo delle sole fibre non trarrà vantaggio da più CPU o più core CPU.


7
Esiste un modo per utilizzare più thread per eseguire fibre in parallelo?
Baradé,

2
@Jason, Quando affermi ~ "con le fibre il percorso di esecuzione corrente viene interrotto solo quando la fibra produce esecuzione" e "le fibre iniziano e si fermano sempre in luoghi ben definiti, quindi l'integrità dei dati è molto meno un problema", vuoi dire che quando si condividono variabili, non è necessario utilizzare "meccanismi di blocco" e variabili volatili? O vuoi dire che dobbiamo ancora fare quelle cose?
Pacerier,

@ Baradé È una domanda interessante, hai trovato una risposta?
Mayur

57

I thread usano la pianificazione preventiva , mentre le fibre usano la cooperazione programmazione .

Con un thread, il flusso di controllo può essere interrotto in qualsiasi momento e può subentrare un altro thread. Con più processori, puoi avere più thread in esecuzione contemporaneamente ( multithreading simultaneo o SMT). Di conseguenza, devi essere molto attento all'accesso simultaneo ai dati e proteggere i tuoi dati con mutex, semafori, variabili di condizione e così via. Spesso è molto difficile ottenere il giusto.

Con una fibra, il controllo passa solo quando lo dici, in genere con una chiamata di funzione chiamata qualcosa di simile yield(). Ciò semplifica l'accesso simultaneo ai dati, poiché non devi preoccuparti dell'atomicità delle strutture dei dati o dei mutex. Finché non cedete, non c'è pericolo di essere anticipati e di avere un'altra fibra che prova a leggere o modificare i dati con cui state lavorando. Di conseguenza, tuttavia, se la tua fibra entra in un ciclo infinito, nessun'altra fibra può funzionare, poiché non stai cedendo.

Puoi anche mescolare fili e fibre, il che dà origine ai problemi affrontati da entrambi. Non raccomandato, ma a volte può essere la cosa giusta da fare se fatto con cura.


3
Penso che un loop infinito sia solo un bug che deve essere risolto, e i thread hanno un vantaggio abbastanza oscuro quando c'è un loop infinito. Il concetto non buggy correlato è quando esiste un processo di lunga durata che l'utente potrebbe voler annullare. In questo caso, indipendentemente dal fatto che tu utilizzi thread o fibre, il processo a lungo termine deve essere cooperativo: solo uccidere il thread potrebbe lasciare incastrate alcune delle tue strutture di dati, quindi un modo migliore è ad esempio che il thread di processo a esecuzione prolungata verifichi periodicamente se fosse stato interrotto. Questo non è molto diverso da una fibra che produce periodicamente.
Evgeni Sergeev

43

In Win32, una fibra è una sorta di thread gestito dall'utente. Una fibra ha il proprio stack, il proprio puntatore di istruzioni, ecc., Ma le fibre non sono programmate dal sistema operativo: è necessario chiamare SwitchToFiber in modo esplicito. I thread, al contrario, sono programmati preventivamente dal sistema operativo. In parole povere, una fibra è un thread gestito a livello di applicazione / runtime anziché essere un vero thread del sistema operativo.

Le conseguenze sono che le fibre sono più economiche e che l'applicazione ha un maggiore controllo sulla pianificazione. Questo può essere importante se l'app crea molte attività simultanee e / o desidera ottimizzare da vicino quando vengono eseguite. Ad esempio, un server di database potrebbe scegliere di utilizzare le fibre anziché i thread.

(Potrebbero esserci altri usi per lo stesso termine; come notato, questa è la definizione di Win32.)


37

Innanzitutto consiglierei di leggere questa spiegazione della differenza tra processi e thread come materiale di base.

Dopo aver letto che è abbastanza semplice. I thread possono essere implementati nel kernel, nello spazio utente, oppure i due possono essere mescolati. Le fibre sono fondamentalmente thread implementati nello spazio utente.

  • Quello che viene generalmente chiamato thread è un thread di esecuzione implementato nel kernel: ciò che è noto come thread del kernel. La pianificazione di un thread del kernel è gestita esclusivamente dal kernel, anche se un thread del kernel può rilasciare volontariamente la CPU dormendo se lo desidera. Un thread del kernel ha il vantaggio di poter usare l'I / O di blocco e lasciare che il kernel si preoccupi della pianificazione. Il suo principale svantaggio è che il cambio di thread è relativamente lento poiché richiede il trapping nel kernel.
  • Le fibre sono thread dello spazio utente la cui pianificazione è gestita nello spazio utente da uno o più thread del kernel in un singolo processo. Questo rende la commutazione della fibra molto veloce. Se si raggruppano tutte le fibre che accedono a un determinato insieme di dati condivisi nel contesto di un singolo thread del kernel e si fa gestire la loro pianificazione da un singolo thread del kernel, è possibile eliminare i problemi di sincronizzazione poiché le fibre verranno effettivamente eseguite in serie e si sarà completato controllo sulla loro programmazione. Raggruppare le fibre correlate in un singolo thread del kernel è importante, poiché il thread in cui sono in esecuzione può essere prevenuto dal kernel. Questo punto non è chiarito in molte altre risposte. Inoltre, se si utilizza l'I / O di blocco in una fibra, l'intero thread del kernel fa parte dei blocchi, comprese tutte le fibre che fanno parte del thread del kernel.

Nella sezione 11.4 "Processi e thread in Windows Vista" in Sistemi operativi moderni, Tanenbaum commenta:

Sebbene le fibre siano pianificate in modo cooperativo, se ci sono più thread che programmano le fibre, è necessaria molta attenta sincronizzazione per assicurarsi che le fibre non interferiscano l'una con l'altra. Per semplificare l'interazione tra thread e fibre, è spesso utile creare solo tanti thread quanti sono i processori per eseguirli e affinare i thread per ogni esecuzione solo su un set distinto di processori disponibili, o anche solo un processore. Ogni filo può quindi eseguire un particolare sottoinsieme delle fibre, stabilendo una relazione uno-a-molti tra fili e fibre che semplifica la sincronizzazione. Anche così ci sono ancora molte difficoltà con le fibre. La maggior parte delle librerie Win32 sono completamente inconsapevoli delle fibre e le applicazioni che tentano di utilizzare le fibre come se fossero thread incontreranno vari errori. Il kernel non ha conoscenza delle fibre e quando una fibra entra nel kernel, il thread su cui sta eseguendo potrebbe bloccarsi e il kernel pianificherà un thread arbitrario sul processore, rendendolo non disponibile per eseguire altre fibre. Per questi motivi le fibre vengono utilizzate raramente tranne quando si esegue il porting di codice da altri sistemi che richiedono esplicitamente la funzionalità fornita dalle fibre.


4
Questa è la risposta più completa.
Bernard,

12

Nota che oltre a thread e fibre, Windows 7 introduce la pianificazione in modalità utente :

La pianificazione in modalità utente (UMS) è un meccanismo leggero che le applicazioni possono utilizzare per pianificare i propri thread. Un'applicazione può passare tra thread UMS in modalità utente senza coinvolgere lo scheduler di sistema e riprendere il controllo del processore se un thread UMS si blocca nel kernel. I thread UMS differiscono dalle fibre in quanto ogni thread UMS ha il proprio contesto di thread invece di condividere il contesto di thread di un singolo thread. La possibilità di passare da un thread all'altro in modalità utente rende UMS più efficiente dei pool di thread per la gestione di un numero elevato di elementi di lavoro di breve durata che richiedono poche chiamate di sistema.

Ulteriori informazioni su fili, fibre e UMS sono disponibili guardando Dave Probert: Inside Windows 7 - User Mode Scheduler (UMS) .


7

Le discussioni sono programmate dal sistema operativo (preventivo). Un thread può essere interrotto o ripreso in qualsiasi momento dal sistema operativo, ma le fibre si gestiscono più o meno da sole (cooperando) e cedono l'una all'altra. Cioè, il programmatore controlla quando le fibre eseguono la loro elaborazione e quando tale elaborazione passa a un'altra fibra.


7

I thread generalmente si affidano al kernel per interrompere il thread in modo che esso o un altro thread possano essere eseguiti (meglio noto come multitasking preventivo) mentre le fibre usano il multitasking cooperativo dove è la fibra stessa a rinunciare al suo tempo di esecuzione in modo che possono correre altre fibre.

Alcuni link utili che lo spiegano meglio di quanto probabilmente abbia fatto sono:


7

I thread sono stati originariamente creati come processi leggeri. In modo simile, le fibre sono un filo leggero, che si affida (semplicisticamente) alle fibre stesse per programmarsi a vicenda, cedendo il controllo.

Immagino che il prossimo passo saranno i fili in cui devi inviare loro un segnale ogni volta che vuoi che eseguano un'istruzione (non diversamente dal mio figlio di 5 anni :-). Ai vecchi tempi (e anche ora su alcune piattaforme incorporate), tutti i thread erano in fibra, non vi era alcuna prelazione e bisognava scrivere i thread per comportarsi bene.


3

La definizione della fibra Win32 è in effetti la definizione "Green Thread" stabilita da Sun Microsystems. Non è necessario sprecare il termine fibra sul thread in qualche modo, ovvero un thread in esecuzione nello spazio utente sotto il controllo del codice utente / libreria di thread.

Per chiarire l'argomento guarda i seguenti commenti:

  • Con l'hyper-threading, la CPU multi-core può accettare più thread e distribuirli uno su ciascun core.
  • La CPU con pipeline Superscalar accetta un thread per l'esecuzione e utilizza il Parallelism a livello di istruzione (ILP) per eseguire il thread più velocemente. Possiamo supporre che un filo sia spezzato in fibre parallele che corrono in condotte parallele.
  • La CPU SMT può accettare più thread e frenarli in fibre di istruzioni per l'esecuzione parallela su più condutture, utilizzando le condutture in modo più efficiente.

Dovremmo presumere che i processi siano fatti di fili e che i fili dovrebbero essere fatti di fibre. Con questa logica in mente, usare le fibre per altri tipi di fili è sbagliato.


Questo è interessante.
JSON,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.