Solo così si sa cosa stava succedendo, un "loop stretto" consuma riparto della CPU del filo, proprio come qualsiasi altro codice tuo thread esegue. L'unica differenza è che non realizza nulla. Beh, immagino che rendere il nucleo caldo sia qualcosa ... Probabilmente non vorrai mai farlo a meno che non ti interessi il costo dell'interruttore di contesto e sai di sicuro che il tempo di attesa sarà molto più breve del timeslice del tuo thread , che è di circa 1ms. Non so se il sonno sia negativo come rendimento (la resa AFAIK imposta il thread sul retro della lista di thread da attivare al tuo livello di priorità), ma entrambi sostengono almeno la penalità di un interruttore di contesto. C'è un costo per il cambio di contesto. Un interruttore di contesto è ciò che accade quando termina il timeslice del thread. Può terminare perché lo hai terminato con un rendimento o un sonno, o se il kernel l'ha terminato prevenendoti. Leggi su SMP e spinlock per capire di più su interruttori di contesto e casi in cui è applicabile un ciclo stretto.
Inoltre, quando dormi, non sai esattamente quando ti sveglierai di nuovo. quindi una delle ragioni per cui potresti non voler dormire è che devi fare qualcosa velocemente.Potresti aspettare un paio di ms prima di essere riprogrammato.
Tutti gli altri hanno fornito la soluzione pthread_cond_wait, che richiede il blocco tramite mutex e sembra diretta e semplice. Le prestazioni potrebbero essere adeguate alle proprie esigenze, ma sono relativamente lente rispetto a una soluzione che utilizza segnali (sigwait and pthread_kill). La complessità ti insidierà.
Non discusso qui è il motivo per cui si blocca un mutex prima di eseguire il test se è necessario attendere la condizione. La ragione è che il codice come questo ha un difetto:
while (x <= y) {
pthread_cond_wait(&cond, &mut);
}
tuo filo potrebbe verificare (X < = Y), vedere che deve aspettare, ma essere pre-epted prima che si attacca al valore della condizione. Qualche altro thread, che ha appena modificato xey, segnala la condizione in quel timeslice prima che il primo thread sia collegato alla condizione. In questo modo, il segnale di condizione viene perso. Quindi, quello che finisce succede ovunque tu modifichi le variabili che influenzano il segnale, devi aggiungere dei blocchi.
pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mut);
Questo può significare che si aggiungono questi blocchi mutex in molti posti diversi e il codice diventa più complesso e più lento a causa di questo. La possibilità di un filo appeso in attesa di una condizione è sempre lì. La soluzione loop, test, sleep non ha nessuno di questi problemi. Quindi, se il tempo di attesa è noto per essere breve, l'uso di sleep in loop è probabilmente una soluzione eccellente. Soprattutto se riesci a dormire per un secondo o più tra un test e l'altro. Se puoi, non preoccuparti di mutex e condizioni. Se il tempo di sonno è breve, come 1ms e il tempo di attesa è lungo, come minuti o ore, allora finirai per sprecare risorse risvegliandoti continuamente e tornando a dormire. Devi giudicare.
Inoltre, tenere presente che a volte il kernel proverà a riattivare immediatamente il thread del cameriere e altre volte ci sarà un ritardo. Se il thread si sveglia troppo presto, si riattiverà mentre il mutex è bloccato e ritorna immediatamente in stato di sospensione fino a quando il mutex non si sblocca. Se questo diventa un problema, segnalare la condizione in questo modo:
pthread_mutex_lock(&mut);
/* modify x and y */
if (x > y) {
pthread_mutex_unlock(&mut);
pthread_cond_broadcast(&cond);
} else
pthread_mutex_unlock(&mut);
Ringraziamenti vanno a user576875, che è esempi di codice ho copiato.
Nota che devi eseguire il ciclo con un ciclo 'while()' come mostrato negli esempi, perché potresti essere svegliato con la condizione non vera. – caf