Sono solo un utente casuale, quindi prendi le seguenti cose con un pizzico di sale.
Wikipedia definisce thread verdi come "thread pianificati da una macchina virtuale (VM) anziché nativamente dal sottostante sistema operativo". I thread verdi emulano gli ambienti con multithreading senza fare affidamento su alcuna funzionalità del sistema operativo nativo e vengono gestiti nello spazio utente anziché nello spazio del kernel, consentendo loro di lavorare in ambienti che non hanno il supporto del thread nativo.
Go (o più esattamente le due implementazioni esistenti) è un linguaggio che produce solo codice nativo - non usa una VM. Inoltre, lo scheduler nelle attuali implementazioni di runtime si basa su thread a livello di sistema operativo (anche quando GOMAXPROCS = 1). Quindi penso che parlare di thread verdi per il modello Go sia un po 'offensivo.
Go persone hanno coniato il termine goroutine soprattutto per evitare la confusione con altri meccanismi di concorrenza (come coroutine o thread o processi leggeri).
Ovviamente, Go supporta un modello di threading M: N, ma sembra molto più vicino al modello di processo di Erlang, che al modello di thread verde di Java.
Ecco alcuni vantaggi del modello Go rispetto ai thread verdi (come implementato nella JVM iniziale):
-
È possibile utilizzare in modo efficace più core o CPU, in modo trasparente per lo sviluppatore. Con Go, lo sviluppatore dovrebbe occuparsi della concorrenza. Il runtime Go si occuperà del parallelismo. Le implementazioni dei thread verdi Java non sono state ridimensionate su più core o CPU.
-
Le chiamate di sistema e C non bloccano lo scheduler (tutte le chiamate di sistema, non solo quelle che supportano I / O multiplex nei loop di eventi). Implementazioni di thread verdi potrebbero bloccare l'intero processo quando è stata effettuata una chiamata di sistema di blocco.
-
Copia o stack segmentati. In Go, non è necessario fornire una dimensione massima dello stack per la goroutine. Lo stack cresce in modo incrementale quando necessario. Una conseguenza è che una goroutine non richiede molta memoria (4KB-8KB), quindi un numero enorme di essi può essere felicemente generato. L'utilizzo di Goroutine può quindi essere pervasivo.
Ora, per rispondere alle critiche:
-
Con Go, non è necessario scrivere uno scheduler userspace: è già fornito con il runtime. È un software complesso, ma è il problema degli sviluppatori Go, non degli utenti Go. Il suo utilizzo è trasparente per gli utenti di Google. Tra gli sviluppatori Go, Dmitri Vyukov è un esperto di programmazione lockfree / waitfree, e sembra essere particolarmente interessato ad affrontare gli eventuali problemi di prestazioni dello scheduler. L'attuale implementazione dello scheduler non è perfetta, ma migliorerà.
-
La sincronizzazione porta problemi di prestazioni e complessità: questo è parzialmente vero anche con Go. Ma si noti che il modello Go cerca di promuovere l'uso di canali e una scomposizione pulita del programma in concurrent goroutines per limitare la complessità della sincronizzazione (cioè condividere i dati comunicando, invece di condividere la memoria per comunicare). A proposito, l'implementazione Go di riferimento fornisce una serie di strumenti per affrontare i problemi di prestazioni e concorrenza, come un profiler , e un rilevatore di corse .
-
Per quanto riguarda l'errore di pagina e "falsi thread multipli", si noti che Go può pianificare goroutine su più thread di sistema. Quando un thread è bloccato per qualsiasi motivo (errore di pagina, blocco delle chiamate di sistema), non impedisce agli altri thread di continuare a pianificare ed eseguire altre goroutine. Ora, è vero che un errore di pagina bloccherà il thread del SO, con tutte le goroutine programmate su questo thread. Tuttavia, in pratica, la memoria heap di Go non dovrebbe essere scambiata. Questo sarebbe lo stesso in Java: i linguaggi raccolti con garbage collection non adattano molto bene la memoria virtuale. Se il tuo programma deve gestire l'errore di pagina in modo aggraziato, probabilmente perché deve gestire una memoria fuori dal mucchio. In tal caso, il wrapping del codice corrispondente con le funzioni di accesso C risolverà semplicemente il problema (poiché ancora una volta C chiama o blocca le chiamate di sistema non blocca mai lo scheduler di Go runtime).
Quindi IMO, le goroutine non sono thread verdi, e la lingua Go e l'implementazione attuale affronta principalmente queste critiche.