Læser-skribent-problemet er et af de vigtigste problemer i parallel programmering . Det er formuleret sådan:
Der er et hukommelsesområde , der kan læses og skrives. Flere tråde har adgang til det, mens lige så mange tråde de vil kan læse på samme tid, men kun én kan skrive. Hvordan giver man en sådan adgangstilstand?
Du kan klare dig med en almindelig mutex , men det er ikke optimalt - computerhukommelsen er normalt designet, så flere tråde frit kan læse og skrive den (det eneste problem er, at der ikke er nogen garanti for, at variablen ikke pludselig ændrer sig under behandlingen) . Dette problem har flere muligheder, forskellige og løsninger. Hvem der skal prioriteres – læseren eller forfatteren – forbliver hos programmøren.
Mens hukommelsen er åben til læsning, giv læserne ubegrænset adgang. Forfattere kan vente, så længe de vil.
Så snart mindst én forfatter dukkede op, fik ingen andre adgang. Alle andre kan være ledige.
Prøveopløsning [1] :
Globale heltal readcount=0, writecount=0; Globale mutexer mutex1, mutex2, w, r LÆSER r.indtast mutex1.enter læsttælling = læsttælling + 1 hvis readcount=1 så w.enter mutex1.blad r.forlade ...læsning... mutex1.enter readcount = readcount - 1 hvis readcount = 0 så w.leave mutex1.blad FORFATTER mutex2.enter skrivetælling = skrivetælling + 1 hvis writecount=1 så r.enter mutex2.blad w.enter ...vi skriver... w.forlade mutex2.enter skrivetælling = skrivetælling - 1 hvis writecount = 0 så r.leave mutex2.bladUndgå nedetid. Med andre ord: uanset andre trådes handlinger, skal læseren eller skribenten passere barrieren på begrænset tid.
Med andre ord bør ingen tråd (læser eller skribent) vente for længe med at erhverve en lås; lock capture-funktionen skulle efter noget tid, hvis låsen svigter, vende tilbage med lock failed flaget , så tråden ikke er tomgang og kan andre ting. Ofte er denne tid nul: optagelsesfunktionen, hvis optagelsen ikke er mulig lige nu, vender straks tilbage.
Globale mutexes: no_writers, no_readers, counter_mutex Globale heltal: nreaders=0 Lokale heltal: forrige, nuværende FORFATTER: no_writers.enter no_readers.enter ... skrivning .... no_writers.leave no_readers.leave LÆSER: no_writers.enter counter_mutex.enter preve:= nlæsere nreaders := nreaders + 1 hvis prev = 0, så no_readers.enter counter_mutex.leave no_writers.leave ...læsning... counter_mutex.enter nreaderst:= nreaders - 1; currente:= nreaders; hvis nuværende = 0, så no_readers.leave counter_mutex.leave;C-kode for gcc gcc -o rw -lpthread -lm rewr.c
#include <pthread.h> #include <stdio.h> #include <math.h> #include <stdlib.h> #include <semaphore.h> #define M 4 //num of WR #define N 3 //num of RE unsigned int iter ; //iteration sem_t accessM , readresM , orderM ; //sem. usignerede int- læsere = 0 ; // Antal læsere, der får adgang til ressourcen void * læser ( void * prem ) { int num1 =* ( int * ) prm ; int i = 0 , r ; for ( i ; i < iter ; i ++ ) { if ( sem_wait ( & orderM ) == 0 ) printf ( "%d Læser %d i kø__________W%d \n " , i , num1 , num1 ); // Husk vores ankomstrækkefølge sem_wait ( & readresM ); // Vi vil manipulere læsertælleren if ( læsere == 0 ) // Hvis der i øjeblikket ingen læsere er (vi kom først)... sem_wait ( & accessM ); // ...anmoder om eksklusiv adgang til ressourcen for læsere læsere ++ ; // Bemærk at der nu er en læser mere sem_post ( & orderM ); // Frigivelsesrækkefølge for ankomst semafor (vi er blevet serveret) sem_post ( & readresM ); // Vi er færdige med at få adgang til antallet af læsere for nu printf ( "%d Læser %d________________W%d virker \n " , i , num1 , num1 ); // Her kan læseren læse ressourcen efter behag r = 1 + rand () % 4 ; søvn ( r ); sem_vent ( & readresM ); // Vi vil manipulere læsernes modlæsere -- ; // Vi tager afsted, der er en læser mindre if ( læsere == 0 ) // Hvis der ikke er flere læsere, der i øjeblikket læser... sem_post ( & accessM ); // ...frigive eksklusiv adgang til ressourcen sem_post ( & readresM ); // Vi er færdige med at få adgang til antallet af læsere for nu } } void * forfatter ( void * prem ) { int num2 =* ( int * ) prm ; int j = 0 , r ; for ( j ; j < iter ; j ++ ) { if ( sem_wait ( & orderM ) == 0 ) printf ( "%d Writer %d i kø__________P%d \n " , j , num2 , num2 ); // Husk vores ankomstrækkefølge sem_wait ( & accessM ); // Anmod om eksklusiv adgang til ressourcen sem_post ( & orderM ); // Frigivelsesrækkefølge for ankomst semafor (vi er blevet serveret) printf ( "%d Writer %d________________P%d \n " , j , num2 , num2 ); // Her kan skribenten ændre ressourcen efter eget ønske r = 1 + rand () % 4 ; søvn ( r ); sem_post ( & accessM ); // Frigiv eksklusiv adgang til ressourcen } } ugyldig hoved () { pthread_t threadRE [ N ]; pthread_t threadWR [ M ]; sem_init ( & accessM , 0 , 1 ); sem_init ( & readresM , 0 , 1 ); sem_init ( & orderM , 0 , 1 ); printf ( "Indtast antallet af iterationer: " ); scanf ( "%d" , & iter ); printf ( "Iter QUEUE/EXECUTION \n " ); int i ; for ( i = 0 ; i < M ; i ++ ) { pthread_create ( & ( threadWR [ i ]), NULL , writer ,( void * ) & i ); } for ( i = 0 ; i < N ; i ++ ) { pthread_create ( & ( threadRE [ i ]), NULL , reader ,( void * ) & i ); } for ( i = 0 ; i < N ; i ++ ) { pthread_join ( trådRE [ i ], NULL ); } for ( i = 0 ; i < M ; i ++ ) { pthread_join ( trådWR [ i ], NULL ); } sem_destroy ( & accessM ); sem_destroy ( & readresM ); sem_destroy ( & orderM ); }Mange læsere XOR én forfatter (XOR-eksklusiv eller ) betragtes ofte som en invariant af dette problem . Dette er ikke sandt, da situationen, hvor der hverken er læsere eller forfattere, også er korrekt.
Invarianten kan udtrykkes ved følgende udsagn:
forfattere == 0 ELLER forfattere == 1 OG læsere == 0hvor forfattere er antallet af forfattere, læsere er antallet af læsere.
Ofte er en simpel hukommelsesbeskyttende mutex suboptimal. For eksempel i et onlinespil ændres listen over spilrum sjældent - når en af spillerne beslutter sig for at åbne et nyt rum, for eksempel en gang med få sekunders mellemrum. Den læses dusinvis af gange på et sekund, og det giver ingen mening at stille klienter op til dette .
Lignende mekanismer (såkaldt læse-skrive-låsning ) findes i mange programmeringssprog og biblioteker. For eksempel.