Hoppa till innehållet

Busy-waiting

Från Wikipedia

Busy-waiting, busy-looping eller spinning är en teknik där en process upprepade gånger kontrollerar om ett tillstånd gäller, exempelvis om en tangentbordsinmatning eller ett datorlås finns tillgängligt. Spinning kan även användas för att generera en godtycklig fördröjning, en teknik som var nödvändig på system som saknade en metod för att vänta en specifik tidslängd. Processorhastigheter varierar kraftigt mellan datorer, speciellt då en del processorer är utformade för att dynamiskt justera hastigheten baserat på externa faktorer, som exempelvis belastningen på operativsystemet. Därför kan spinning som en tidsfördröjningsteknik ofta producera oförutsägbara eller t.o.m. inkonsistenta resultat såvida koden är implementerad för att bestämma hur snabbt processorn kan köra en tom loop, eller om loopkoden kollar en realtidsklocka.

Spinning kan vara en bra strategi i vissa förhållanden, i synnerhet för implementationen av spinlock inom operativsystem som är byggda att köras på SMP-system. I allmänhet ses spinning som ett antimönster och bör undvikas då processortiden skulle kunna användas för att utföra en annan uppgift istället för att slösa på den på en meningslös aktivitet.

Följande kod skriven i C illustrerar två trådar som delar ett globalt heltal i. Den första tråden använder busy-waiting för att kolla efter en ändring i värdet för i:

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
 
volatile int i = 0; /* i är global, så den är synlig för alla funktioner.
                       Den är även volatile, eftersom den
                       kanske ändras på ett sätt som kompilatorn inte kan förutspå,
                       här ifrån en annan tråd. */
 
/* f1 använder ett spinlock för att vänta på i att ska ändras från 0. */
static void *f1(void *p)
{
    while (i==0) {
        /* gör ingenting - fortsätt vänta om och om igen */
    } 
    printf("i's value has changed to %d.\n", i);
    return NULL;
}

static void *f2(void *p)
{
    sleep(60);   /* vila i 60 sekunder */
    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;
}

I ett fall som detta kan C11:s condition variable användas istället.

Den här artikeln är helt eller delvis baserad på material från engelskspråkiga Wikipedia.

Externa länkar

[redigera | redigera wikitext]