Busy waiting
A számítógép-programozásban a busy waiting, spinning vagy tevékeny várakozás azt jelenti, hogy egy folyamat újra és újra ellenőrzi, hogy egy feltétel igazzá vált-e, például hogy elérhető-e a bemenet a billentyűzetről, vagy hogy felszabadult-e egy erőforrás. Azokon a rendszereken, ahol még nem volt lehetőség a tetszőleges ideig tartó várakozásra, ezzel a módszerrel valósították meg a várakozást. Azonban a számítógépek sebessége különböző, és egy gép sebessége is változhat, különösen akkor, ha úgy van tervezve, hogy sebességét külső tényezőkhöz, például a terheléstől, így ez a módszer ma már nem szolgáltat megbízható eredményt. A kódnak meg kell határoznia, mennyi idő alatt hajtható végre egy várakozó ciklus, vagy pedig külső órát kell ellenőriznie.
Néha a busy waiting megfelelő stratégia, például SMP rendszerekre írt operációs rendszerekben bizonyos lockokra való várakozáskor (spinlock). Általában azonban antimintának tekinthető és kerülendő, mivel pazarolja a processzoridőt, amit hasznosabb feladatokra is lehetne használni.
C példa
[szerkesztés]Az alábbi C nyelvű kód két szálat tartalmaz, amelyek egy globális i változón osztoznak. Az első szál busy waitinget használ annak ellenőrzésére, hogy az i változó értéke megváltozott-e:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
volatile int i = 0; /* i is global, so it is visible to all functions.
It's also marked volatile, because it
may change in a way which is not predictable by the compiler,
here from a different thread. Thus preventing the compiler from
caching its value.*/
/* f1 uses a spinlock to wait for i to change from 0. */
static void *f1(void *p)
{
while (i==0) {
/* do nothing - just keep checking over and over */
}
printf("i's value has changed to %d.\n", i);
return NULL;
}
static void *f2(void *p)
{
sleep(60); /* sleep for 60 seconds */
i = 99;
printf("t2 has changed the value of i to %d.\n", i);
return NULL;
}
int main()
{
int rc;
pthread_t t1, t2;
rc = pthread_create(&t1, NULL, f1, NULL);
if (rc != 0) {
fprintf(stderr,"pthread f1 failed\n");
return EXIT_FAILURE;
}
rc = pthread_create(&t2, NULL, f2, NULL);
if (rc != 0) {
fprintf(stderr,"pthread f2 failed\n");
return EXIT_FAILURE;
}
pthread_join(t1, NULL);
pthread_join(t2, NULL);
puts("All pthreads finished.");
return 0;
}
A hasonló esetek megfelelő kezelésére a C11 óta elérhetők a monitorok feltételváltozói.
Alternatívák
[szerkesztés]A legtöbb operációs rendszer és szálkezelő könyvtár sok rendszerhívást biztosít, melyekkel egy folyamat megvárhatja egy esemény bekövetkezését, mint egy zár megszerzését, időzítést, I/O elérhetőséget vagy szignálokat. Használatuk egyszerűbb, hatékonyabb, korrekt, és versenyhelyzet nélküli eredményt hoz. Egy hívás ellenőriz, majd szól az ütemezőnek, hogy mire vár. Ezután még végezhet némi írás-olvasást, memóriakezelést, mielőtt elalszik. Amíg nem következik be az esemény, addig az ütemező nem ütemezi, így mások kerülnek sorra, és használhatják az erőforrásokat. Az ütemező gondoskodik arról, hogy ne éheztessék ki a várakozó folyamatot.
Maga a busy waiting is tehető kevésbé megterhelővé, ha ritkábbá teszik a lekérdezést, azaz a ciklus nagy részében alszik a szál, és csak néha kérdez. Ekkor a várakozási idő nagy részében nem csinál semmit, a többi szál haladhat tovább.
Soha véget nem érő programokban mint például egy operációs rendszer, a végtelen busy waiting megvalósítható feltétel nélküli ugrásokkal. A NASM szintaxisában a jmp $ azt jelenti, hogy a processzor mindig a saját pozíciójára ugrik. A busy waiting helyettesíthető, mint:
sleep:
hlt
jmp sleep
(Lásd még: HLT (x86 utasítás)).
Megfelelő használat
[szerkesztés]Alacsony szinten a busy waiting megfelelő lehet. Nem alkalmas megszakítás-vezérelt folyamatfeldolgozásra minden eszközön, különösen azokon, amelyeket ritkán használnak. Néha vezérlési adatokat kell írni a hardverre és az író műveletek eredményeit elhozni, ami nem válik azonnal érvényessé, hanem el kell telnie bizonyos számú ciklusnak. Az operációs rendszer delay függvényének meghívása hosszabb időt vesz igénybe, mint ezt az időt busy waitinggel kivárni, különösen ha csak néhány ciklusról van szó.
Források
[szerkesztés]- Description from The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
- Article "User-Level Spin Locks - Threads, Processes & IPC" by Gert Boddaert
- Austria SpinLock Class Reference Archiválva 2011. május 14-i dátummal a Wayback Machine-ben
Fordítás
[szerkesztés]Ez a szócikk részben vagy egészben a Busy waiting című angol Wikipédia-szócikk fordításán alapul. Az eredeti cikk szerkesztőit annak laptörténete sorolja fel. Ez a jelzés csupán a megfogalmazás eredetét és a szerzői jogokat jelzi, nem szolgál a cikkben szereplő információk forrásmegjelöléseként.