Problema de lector-escritor usando monitores (pthreads)

Requisito previo: monitores , lectores y escritores Problema 
Hay un recurso compartido al que acceden varios procesos, es decir, lectores y escritores. Cualquier número de lectores puede leer del recurso compartido simultáneamente, pero solo un escritor puede escribir en el recurso compartido a la vez. Cuando un escritor escribe datos en el recurso, ningún otro proceso puede acceder al recurso. Un escritor no puede escribir en el recurso si hay lectores accediendo al recurso en ese momento. De manera similar, un lector no puede leer si hay un escritor accediendo al recurso o si hay escritores esperando.
El problema de Reader-Writer usando un monitor se puede implementar usando pthreads. Los hilos POSIX (o pthread)Las bibliotecas son una API de subprocesos basada en estándares para C/C++. La biblioteca proporciona los siguientes mecanismos de sincronización: 
 

  • Mutexes (pthread_mutex_t) – Bloqueo de exclusión mutua: 
    bloquea el acceso a las variables por parte de otros subprocesos. Esto impone el acceso exclusivo de un subproceso a una variable o conjunto de variables. 
     
  • Variables de condición – (pthread_cond_t): 
    el mecanismo de variable de condición permite que los subprocesos suspendan la ejecución y renuncien al procesador hasta que se cumpla alguna condición. 
     

Implementación de la solución Reader-Writer usando la biblioteca pthread:
Ejecute el programa usando el siguiente comando en su sistema Linux 
 

$g++ -pthread program_name.cpp
$./a.out
or
$g++ -pthread program_name.cpp -o object_name
$./object_name

Código:

CPP

// Reader-Writer problem using monitors
 
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
 
class monitor {
private:
    // no. of readers
    int rcnt;
 
    // no. of writers
    int wcnt;
 
    // no. of readers waiting
    int waitr;
 
    // no. of writers waiting
    int waitw;
 
    // condition variable to check whether reader can read
    pthread_cond_t canread;
 
    // condition variable to check whether writer can write
    pthread_cond_t canwrite;
 
    // mutex for synchronization
    pthread_mutex_t condlock;
 
public:
    monitor()
    {
        rcnt = 0;
        wcnt = 0;
        waitr = 0;
        waitw = 0;
 
        pthread_cond_init(&canread, NULL);
        pthread_cond_init(&canwrite, NULL);
        pthread_mutex_init(&condlock, NULL);
    }
 
    // mutex provide synchronization so that no other thread
    // can change the value of data
    void beginread(int i)
    {
        pthread_mutex_lock(&condlock);
 
        // if there are active or waiting writers
        if (wcnt == 1 || waitw > 0) {
            // incrementing waiting readers
            waitr++;
 
            // reader suspended
            pthread_cond_wait(&canread, &condlock);
            waitr--;
        }
 
        // else reader reads the resource
        rcnt++;
        cout << "reader " << i << " is reading\n";
        pthread_mutex_unlock(&condlock);
        pthread_cond_broadcast(&canread);
    }
 
    void endread(int i)
    {
 
        // if there are no readers left then writer enters monitor
        pthread_mutex_lock(&condlock);
 
        if (--rcnt == 0)
            pthread_cond_signal(&canwrite);
 
        pthread_mutex_unlock(&condlock);
    }
 
    void beginwrite(int i)
    {
        pthread_mutex_lock(&condlock);
 
        // a writer can enter when there are no active
        // or waiting readers or other writer
        if (wcnt == 1 || rcnt > 0) {
            ++waitw;
            pthread_cond_wait(&canwrite, &condlock);
            --waitw;
        }
        wcnt = 1;
        cout << "writer " << i << " is writing\n";
        pthread_mutex_unlock(&condlock);
    }
 
    void endwrite(int i)
    {
        pthread_mutex_lock(&condlock);
        wcnt = 0;
 
        // if any readers are waiting, threads are unblocked
        if (waitr > 0)
            pthread_cond_signal(&canread);
        else
            pthread_cond_signal(&canwrite);
        pthread_mutex_unlock(&condlock);
    }
 
}
 
// global object of monitor class
M;
 
void* reader(void* id)
{
    int c = 0;
    int i = *(int*)id;
 
    // each reader attempts to read 5 times
    while (c < 5) {
        usleep(1);
        M.beginread(i);
        M.endread(i);
        c++;
    }
}
 
void* writer(void* id)
{
    int c = 0;
    int i = *(int*)id;
 
    // each writer attempts to write 5 times
    while (c < 5) {
        usleep(1);
        M.beginwrite(i);
        M.endwrite(i);
        c++;
    }
}
 
int main()
{
    pthread_t r[5], w[5];
    int id[5];
    for (int i = 0; i < 5; i++) {
        id[i] = i;
 
        // creating threads which execute reader function
        pthread_create(&r[i], NULL, &reader, &id[i]);
 
        // creating threads which execute writer function
        pthread_create(&w[i], NULL, &writer, &id[i]);
    }
 
    for (int i = 0; i < 5; i++) {
        pthread_join(r[i], NULL);
    }
    for (int i = 0; i < 5; i++) {
        pthread_join(w[i], NULL);
    }
}

Producción:
 

Publicación traducida automáticamente

Artículo escrito por PrachiHooda y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *