Problema dos Leitores e Escritores
Aluno: Misael Alexandre

Codificação

O problema dos leitores e escritores modela o acesso a uma base de dados. O problema consiste em uma base de dados. Vários leitores podem ter acesso a essa base ao mesmo tempo. Entretanto, se alguém estiver escrevendo, nem mesmo os leitores podem ver a base de dados (já que está inconsistente). A questão é implementar sem condições de disputa.

Na implementação, além das threads usadas para a criação dos leitores e escritores, foi usado um semáforo para controlar o acesso ao número de leitores lendo ou querendo ler e um mutex para controlar o acesso a base de dados. O algoritmo de implementação utilizado foi o dado no Tanenbaum. O código implementado é dado abaixo.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
 
#define ESCRITORES 10
#define LEITORES 10
 
int i, j, int_rand, rc, total;
float float_rand;
char phrase[500]="";
char increment[500];
 
sem_t mutex;
pthread_mutex_t db;
 
void *reader(void *j){
   int i= *(int*) j;
   while(1){
    sem_wait(&mutex);
    rc=rc+1;
    if(rc==1) pthread_mutex_lock(&db);
    sem_post(&mutex);
    read_data_base(i);
    sem_wait(&mutex);
    rc=rc-1;
    if(rc==0) pthread_mutex_unlock(&db);
    sem_post(&mutex);
    use_data_read(i);
 
        float_rand=0.01*random();
        int_rand=float_rand;
        usleep(int_rand);
 
   }
 
}
 
void *writer(void *j){
   int i= *(int*) j;
   while(1){
    think_up_data(i);
    pthread_mutex_lock(&db);
    write_data_base(i);
        pthread_mutex_unlock(&db);
 
        float_rand=0.01*random();
        int_rand=float_rand;
        usleep(int_rand);
 
   }
}
 
void read_data_base(int i){
   printf("O leitor %d le: %s\n",i,phrase);
}
 
void use_data_read(int i){
   printf("O leitor %d usa o que leu.\n",i);
}
 
void think_up_data(int i){
   printf("O escritor %d inventa um dado para colocar.\n",i);
   increment[0]=' ';
   increment[1]='a';
   increment[2]=' ';
}
 
void write_data_base(int i){
   strcat(phrase,increment);
   printf("O escritor %d coloca o dado na base de dados: %s\n",i,phrase);
}  
 
void main(){
 
        rc=0;
 
    int res;
 
        total=LEITORES+ESCRITORES;
    pthread_t thread[total];
 
    void *thread_result;
 
    res = sem_init(&mutex,0,1);
    if(res!=0){
       perror("Erro na inicialização do mutex!");
       exit(EXIT_FAILURE);
    }
 
    res = pthread_mutex_init(&db,NULL);
    if(res!=0){
       perror("Erro na inicialização do semaforo!");
       exit(EXIT_FAILURE);
    }
 
    for(i=0; i<ESCRITORES; i++){
       res = pthread_create(&thread[i],NULL,writer,&i);
       if(res!=0){
          perror("Erro na inicialização da thread!");
          exit(EXIT_FAILURE);
       }
    }
 
        for(i=ESCRITORES; i < total; i++){
       res = pthread_create(&thread[i],NULL,reader,&i);
       if(res!=0){
          perror("Erro na inicialização da thread!");
          exit(EXIT_FAILURE);
       }
    }
 
        for(i=0; i < total; i++){
       res = pthread_join(thread[i],&thread_result);
       if(res!=0){
          perror("Erro ao fazer join nas threads!");
          exit(EXIT_FAILURE);
       }
    }
}

Foi colocada uma espera aleatória após cada leitura ou escrita para que aparecessem mais condições de disputa e um maior intercalamento entre leituras e escritas.

A base de dados implementada, a fins de simplificação, foi uma string chamada phrase que era lida pelos leitores e incrementada de " a " pelos escritores.

Teste

Foi feito um teste com 10 leitores e 10 escritores. O resultado é mostrado na figura abaixo.

leitores.jpg

Dificuldades

Não houve dificuldades para fazer este programa.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License