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.
Dificuldades
Não houve dificuldades para fazer este programa.