Idle loop (de asemenea, „idle waiting”, engleză busy waiting) - implementarea așteptării într-un program de calculator, în care o anumită condiție este verificată într-o buclă fără sfârșit. Ieșirea din bucla infinită are loc numai atunci când condiția testată este îndeplinită.
De asemenea, o buclă inactivă poate fi utilizată pentru a crea o întârziere arbitrară în execuția programului.
În cele mai multe cazuri, bucla inactivă este considerată un anti-pattern care ar trebui evitat prin refactorizarea codului sau folosind o abordare diferită de dezvoltare (execuție asincronă, programare bazată pe evenimente etc.).
În fragmentul de cod de mai jos, unul dintre fire așteaptă valoarea 0 în variabila i și numai după aceea continuă execuția:
# include <pthread.h> # include <stdatomic.h> # include <stdio.h> # include <stdlib.h> # include <unistd.h> /* i este global, deci este vizibil pentru toate funcțiile. Face uz de special * tastați atomic_int, care permite accesarea memoriei atomice. */ atom_int i = 0 ; /* f1 folosește un spinlock pentru a aștepta ca i să se schimbe de la 0. */ gol static * f1 ( gol * p ) { int local_i ; /* Încărcați atomic valoarea curentă a lui i în local_i și verificați dacă acea valoare este zero */ în timp ce (( local_i = sarcină_atomică ( & i )) == 0 ) { /* nu face nimic - continuă să verifici iar și iar */ } printf ( "valoarea lui i s-a schimbat la %d. \n " , local_i ); returnează NULL ; } gol static * f2 ( gol * p ) { int local_i = 99 ; somn ( 10 ); /* dormi 10 secunde */ depozit_atomic ( & i , local_i ); printf ( "t2 a schimbat valoarea lui i la %d. \n " , local_i ); returnează NULL ; } int main () { int rc ; pthread_t t1 , t2 ; rc = pthread_create ( & t1 , NULL , f1 , NULL ); dacă ( rc != 0 ) { fprintf ( stderr , "pthread f1 a eșuat \n " ); returnează EXIT_FAILURE ; } rc = pthread_create ( & t2 , NULL , f2 , NULL ); dacă ( rc != 0 ) { fprintf ( stderr , "pthread f2 a eșuat \n " ); returnează EXIT_FAILURE ; } pthread_join ( t1 , NULL ); pthread_join ( t2 , NULL ); puts ( "Toate pthreadurile s-au terminat." ); returnează 0 ; }Această implementare folosește un apel la metoda Thread.sleep() într-o buclă, care vă permite să suspendați execuția unui fir pentru un anumit număr de milisecunde:
întârziere lungă = 1L ; // timp în milisecunde boolean volatil waitForEvent = true ; // valoarea este setată din alte fire în timp ce ( waitForEvent ) { fir . somn ( întârziere ); }În același timp, planificatorul oferă resurse de calcul altor fire, motiv pentru care „adormirea” și „trezirea” unui fir sunt operațiuni costisitoare. Un alt dezavantaj al acestei metode este necesitatea de a gestiona excepția, precum și incapacitatea de a suspenda firul pentru mai puțin de 1 milisecundă. Începând cu Java 9, a fost introdusă metoda Thread.onSpinWait(), care vă permite să implementați o scurtă așteptare fără a întrerupe firul:
boolean volatil waitForEvent = true ; // valoarea este setată din alte fire în timp ce ( waitForEvent ) { fir . onSpitWait (); }Avantajul acestei abordări este capacitatea de a întrerupe imediat așteptarea și de a continua execuția.
Unul dintre subtipurile de așteptare inactivă este un spinlock.
În programarea de nivel scăzut, buclele inactive sunt utilizate mai pe scară largă. În practică, o întrerupere nu este întotdeauna de dorit pentru unele dispozitive hardware. De exemplu, dacă este necesar să scrieți unele informații de control pe dispozitiv și să primiți un răspuns despre rezultatele scrierii, dezvoltatorul poate apela la funcția de întârziere la nivelul sistemului de operare, dar apelul său poate dura mai mult, așa că o așteptare activă se utilizează ciclul.