2009-04-28 21 views

risposta

120

Nei termini più semplici, i thread sono generalmente considerati come preventivi (anche se questo potrebbe non essere sempre vero, a seconda del sistema operativo) mentre le fibre sono considerate fili leggeri e cooperativi. Entrambi sono percorsi di esecuzione separati per la tua applicazione.

Con thread: il percorso di esecuzione corrente può essere interrotto o azzerato in qualsiasi momento (nota: questa istruzione è una generalizzazione e potrebbe non essere sempre valida 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 fermato nel mezzo dell'aggiornamento di una porzione 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 CPU eseguendo più di un thread contemporaneamente e lasciandolo allo sviluppatore per proteggere l'accesso ai dati.

Con fibre: il percorso di esecuzione corrente viene interrotto solo quando la fibra produce un'esecuzione (stessa nota come sopra). Ciò significa che le fibre iniziano e si fermano sempre in luoghi ben definiti, quindi l'integrità dei dati è molto meno problematica. Inoltre, poiché le fibre vengono spesso gestite nello spazio utente, non è necessario apportare costosi switch di contesto e modifiche allo stato della CPU, rendendo estremamente efficiente il passaggio da una fibra all'altra. D'altra parte, dal momento che non è possibile eseguire due fibre esattamente nello stesso momento, l'utilizzo delle sole fibre non sfrutta più CPU o più core CPU.

+5

Esiste un modo per utilizzare più thread per eseguire le fibre in parallelo? –

+1

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

42

In Win32, una fibra è una sorta di thread gestito dall'utente. Una fibra ha il suo stack e il suo puntatore di istruzioni, ecc., Ma le fibre non sono programmate dal sistema operativo: devi chiamare SwitchToFiber in modo esplicito. Le discussioni, al contrario, sono pianificate preventivamente dal sistema operativo. Quindi, approssimativamente, una fibra è un thread gestito a livello di applicazione/runtime piuttosto che un vero thread del sistema operativo.

Le conseguenze sono che le fibre sono più economiche e che l'applicazione ha più controllo sulla programmazione. 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 fibre anziché thread.

(Ci possono essere altri utilizzi per la stessa durata, come osservato, questa è la definizione Win32.)

7

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

5

I thread si basano generalmente sul kernel per interrompere il thread in modo che possa essere eseguito da un altro thread (meglio noto come multitasking preventivo) mentre le fibre utilizzano il multitasking cooperativo in cui è la fibra stessa a rinunciare al suo tempo di esecuzione in modo che altre fibre possano funzionare.

Alcuni link utili che spiegano meglio di probabilmente ho fatto sono:

42

discussioni utilizzano preventiva programmazione, mentre le fibre utilizzano cooperativa scheduli ng.

Con un thread, il flusso di controllo potrebbe interrompersi in qualsiasi momento e un altro thread può prendere il sopravvento. Con più processori, è possibile avere più thread tutti in esecuzione contemporaneamente (simultaneo con il multithreading o SMT). Di conseguenza, è necessario essere molto attento sull'accesso simultaneo ai dati e proteggere i dati con mutex, semafori, variabili di condizione e così via. Spesso è molto complicato avere ragione.

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

È inoltre possibile combinare fili e fibre, dando origine ai problemi affrontati da entrambi. Non consigliato, ma a volte può essere la cosa giusta da fare se fatto con attenzione.

+2

Penso che un ciclo infinito sia solo un bug che deve essere corretto e che i thread hanno un vantaggio piuttosto oscuro quando c'è un ciclo infinito. Il relativo concetto non buggato è quando c'è un processo di lunga durata che l'utente potrebbe desiderare di cancellare. In questo caso, sia che si utilizzino thread o fibre, il processo di lunga durata deve essere collaborativo: basta uccidere il thread potrebbe lasciare incasinate alcune delle strutture dati, quindi un modo migliore è ad es. il thread del processo di lunga durata controllerebbe periodicamente se fosse stato interrotto. Questo non è tanto diverso da una fibra che produce periodicamente. –

6

I thread sono stati originariamente creati come processi leggeri. In modo simile, le fibre sono un filo leggero, che si basa (in modo semplicistico) sulle fibre stesse per pianificare l'un l'altro, ottenendo il controllo.

Credo che il prossimo passo saranno fili in cui devi inviare loro un segnale ogni volta che vuoi che eseguano un'istruzione (non diversamente dal mio figlio 5yo :-). Ai vecchi tempi (e anche ora su alcune piattaforme embedded), tutti i thread erano fibre, non c'era la prelazione e dovevi scrivere i tuoi thread per comportarsi bene.

12

noti che oltre ai fili e fibre, Windows 7 introduce User-Mode Scheduling:

-modalità utente pianificazione (UMS) è un meccanismo leggera che applicazioni possono usare per programmare le propri thread. Un'applicazione può passare da tra i thread UMS in modalità utente senza coinvolgere lo scheduler di sistema e riprendere il controllo del processore se blocchi di thread UMS nel kernel. I thread UMS differiscono dalle fibre in quanto ogni thread UMS ha il proprio contesto thread invece di condividere il contesto thread di un singolo thread. La possibilità di passare tra thread nella modalità utente rende UMS più efficiente rispetto ai pool di thread per la gestione di grandi numeri di articoli di breve durata che richiedono alcune chiamate di sistema.

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

30

Prima di tutto raccomanderei di leggere questa spiegazione di the difference between processes and threads come materiale di base.

Una volta letto, è abbastanza semplice. I thread possono essere implementati nel kernel, nello spazio utente, oppure i due possono essere mescolati. Le fibre sono fondamentalmente thread implementate nello spazio dell'utente.

  • Ciò che è tipicamente chiamato un filo è un filo di esecuzione implementati nel kernel: ciò che è noto come un filo kernel. La programmazione di un thread del kernel è gestita esclusivamente dal kernel, sebbene un thread del kernel possa rilasciare volontariamente la CPU dormendo se lo desidera. Un thread del kernel ha il vantaggio di poter utilizzare l'I/O di blocco e lasciare che il kernel si preoccupi della programmazione. Lo svantaggio principale è che il cambio di thread è relativamente lento poiché richiede il trapping nel kernel.
  • Le fibre sono thread dello spazio utente la cui pianificazione viene gestita nello spazio utente da uno o più thread del kernel in un singolo processo. Questo rende la commutazione delle fibre molto veloce. Se si raggruppano tutte le fibre che accedono a un particolare insieme di dati condivisi nel contesto di un singolo thread del kernel e la loro pianificazione è gestita da un singolo thread del kernel, è possibile eliminare i problemi di sincronizzazione poiché le fibre funzioneranno in modo seriale e completo. controllo sulla loro programmazione. Raggruppare le fibre correlate in un singolo thread del kernel è importante, poiché il thread del kernel in cui sono in esecuzione può essere anticipato dal kernel. Questo punto non è chiarito in molte delle altre risposte. Inoltre, se si utilizza l'I/O di blocco in una fibra, l'intero thread del kernel è una parte di blocchi che include tutte le fibre che fanno parte del thread del kernel.

Nella sezione 11.4 "Processi e thread in Windows Vista" nei sistemi operativi moderni, commenti Tanenbaum:

Anche se le fibre sono in modo cooperativo in programma, se ci sono più discussioni la pianificazione delle fibre, un sacco di un'attenta sincronizzazione è richiesta per assicurarsi che le fibre non interferiscano l'una con l'altra. Per semplificare l'interazione tra fili e fibre, è spesso utile creare solo tanti fili quante sono processori per eseguire loro, e affinità tra i fili di ogni esecuzione solo su un insieme distinto di processori disponibili, o anche solo un processore. Ogni thread può quindi eseguire un sottoinsieme particolare delle fibre, stabilendo una relazione uno-a-molti tra thread 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 si trattasse di thread verificheranno vari errori. . Il kernel non ha conoscenza delle fibre, e quando una fibra entra nel kernel, il thread su cui si sta eseguendo può e il kernel pianifica un thread arbitrario sul processore , rendendolo non disponibile per l'esecuzione di 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.

+3

Questa è la risposta più completa. – Alkaline

1

definizione fibra Win32 è in realtà "Green Thread" definizione stabilita di Sun Microsystems. Non è necessario sprecare il termine fibra sul thread di qualche tipo, cioè un thread che si esegue nello spazio utente sotto il controllo codice utente/libreria di thread.

Per chiarire l'aspetto argomento ai seguenti osservazioni:

  • con tecnologia Hyper-threading, CPU multi-core può accettare più thread e distribuirli uno per ogni core.
  • La CPU pipeline in superscalare accetta un thread per l'esecuzione e utilizza Parallelismo del livello di istruzione (ILP) per eseguire il thread più rapidamente.Possiamo presumere che un filo sia rotto in fibre parallele che corrono in condutture parallele.
  • SMT CPU può accettare più thread e li frena in fibre di istruzioni per l'esecuzione parallela di su più pipeline, utilizzando le tubazioni 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.

0

Una fibra è un thread leggero che utilizza il multitasking cooperativo anziché il multitasking preventivo. Una fibra funzionante deve "produrre" esplicitamente per consentire l'esecuzione di un'altra fibra, il che rende la loro implementazione molto più semplice rispetto ai thread del kernel o dell'utente.

Una Coroutine è un componente che generalizza una subroutine per consentire più punti di ingresso per sospendere e riprendere l'esecuzione in determinate posizioni. Diversamente dalle subroutine, le coroutine possono uscire chiamando altre coroutine, che possono successivamente ritornare al punto in cui sono state invocate nella coroutine originale.

Problemi correlati