Questa potrebbe essere una domanda molto semplice. Sono curioso di come vengono implementate le chiamate di blocco. Nello specifico, come bloccano? È solo thread.sleep?
Questa potrebbe essere una domanda molto semplice. Sono curioso di come vengono implementate le chiamate di blocco. Nello specifico, come bloccano? È solo thread.sleep?
Specifically, I was implementing a socket class in C# and one of the .Net socket methods blocks until data is received. I was just curious how that works.
Ci sono diversi modi per implementare una chiamata di blocco. Il modo più ovvio per farlo è tornare quando il lavoro è finito Vedi la risposta di Robert Harvey .
Nel caso in cui non ci sia lavoro da fare (ad esempio, in attesa di un segnale o di input), ci sono diverse scelte:
while(signal not found){}
. Gli spinlock non hanno quasi nessun sovraccarico e ritornano più velocemente di altri metodi, ma bruciano la CPU fino al loro ritorno. Sono utili se il segnale che stai aspettando sta per tornare fast o se rinunciare a un timeslice deve essere evitato, ma generalmente è una cattiva idea nel codice di alto livello. lock(obj){}
(perché altri thread da bloccare) e ManualResetEvent
(bloccare fino a quando un altro thread segnala). Generalmente, sono implementati a livello di kernel o hardware. Ad esempio, il blocco C # viene implementato su macchine x86 utilizzando l'istruzione assembly assembly lock cmpxchg
( vedi il blog di Junfeng Zhang ). I metodi non controllano return
al chiamante fino a quando il loro lavoro non è completato, tutto qui. Nell'esempio della classe socket, il metodo non return
dei dati finché non li riceve effettivamente.
Nella maggior parte dei casi, dove stai vedendo qualcosa come Thread.Sleep(1000)
in un esempio di codice, non vedi il blocco di per sé, ma semplicemente simula il lavoro.
Dove Thread.Sleep
viene utilizzato legittimamente, sta cedendo il controllo ad altri thread, con una dichiarazione implicita: "Posso aspettare un po 'prima di restituirmi il controllo". Thread.Sleep
non richiesto; il sistema operativo normalmente preleverà il thread per brevi periodi di tempo, comunque, se è necessario completare anche il lavoro su altri thread.
Nella maggior parte delle chiamate di sistema nella maggior parte dei sistemi operativi, la chiamata di blocco alla fine fa sì che alcune richieste vengano eseguite dal kernel mentre il thread chiamante viene sospeso dallo scheduler / dispatcher fino al completamento del lavoro. In genere questo lavoro è una sorta di richiesta di I / O per l'hardware periferico (ad es. Scheda di rete / disco fisso / ecc.). L'hardware periferico può utilizzare un interrupt del processore per segnalare alla CPU / kernel che parte del lavoro è completa (o qualche altra informazione sul lavoro). Una volta completato il lavoro, il kernel riattiva il thread chiamante e consente di continuare l'esecuzione da dove era in attesa. Insieme hardware / kernel hanno preparato le uscite (buffer / errori, ecc.) Per la funzione di chiamata rivolta all'utente e queste uscite vengono restituite al chiamante.
I dettagli specifici di come ciò accadrà saranno molto diversi a seconda del sistema operativo sottostante. Per un approfondimento sul funzionamento di Windows, consiglio: Pianificazione, contesto del thread e IRQL .
Leggi altre domande sui tag .net