Leitores e Escritores

INTRODUÇÃO

Mais um problema famoso de comunicação interprocesso que modela o acesso a uma base de dados é o problema dos leitores e escritoes.
Em um sistema com muitos processo querendo ler e escrever em uma arquivo, é aceitável que múltiplos processos leiam a base de dados ao mesmo tempo, mas, se um processo estiver escrevendo na base de dados, nenhum outro processo pode ter acesso ao bando de dados, nem mesmo os leitores.

IMPLEMENTAÇÃO

Para implementar o problema dos leitores e escritores, foi requisitado o uso de mutex e semáforos

/* ***********************************************************
Implementação da solução do problema leitore e escritores
utilizando mutexes e threads
 
O programa recebe 2 parametro:
 - primeiro corresponde ao número de escritores para gerar
 - segundo corresponde ao número de leitores para gerar 
 
Tiago Porto, Maio 2009
 
*********************************************************** */
 
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
 
#define TRUE 1
#define FALSE 0
#define MAX 100
 
void *reader(void *arg);
void *writer(void *arg);
void read_data_base(int i);
void use_data_read(int i);
void think_up_data(int i);
void write_data_base(int i);
 
/* Variaveis globais */
pthread_mutex_t mutex;  
sem_t db;
int rc;
 
main(int argc, void* argv[]) {
    rc=0;
    pthread_t writer_thread[MAX], reader_thread[MAX];
    int i, res, res1;
 
    /* Iniciando semoros */
    res=sem_init(&db, 0, 1);
    res1=pthread_mutex_init(&mutex, NULL);
    if(res!=0 || res1!=0){
        perror("Falha na inicializacao do semaforo");
        exit(1);
    }
    /* Criando escritores */
    for(i=0; i<atoi(argv[1]); i++){
        res = pthread_create(&writer_thread[i], NULL, writer, (void *)i);
        if(res!=0){
            perror("Falha na inicializacao dos escritores");
            exit(1);
        }
    }
    /* Criando leitores */
    for(i=0; i<atoi(argv[2]); i++){
        res = pthread_create(&reader_thread[i], NULL, reader, (void *)i);
        if(res!=0){
            perror("Falha na inicializacao dos leitores");
            exit(1);
        }
    }
    /* Espera por um caractere */
    getchar();    
}
/* Função do leitor */
void *reader(void *arg){
    int i = (int) arg;
    printf("Leitor %d criado\n", i);
    while (TRUE){
        pthread_mutex_lock(&mutex);
        rc ++;
        if (rc==1){
            printf("Leitor %d tentando ler base de dados.\n", i);
            sem_wait(&db);
        }
        pthread_mutex_unlock(&mutex);
        read_data_base(i);
        printf("Leitor %d leu base de dados.\n", i);
        pthread_mutex_lock(&mutex);
        rc --;
        if (rc==0) 
            sem_post(&db);
        pthread_mutex_unlock(&mutex);
        use_data_read(i);
    }
}
/* Função do escritor */
void *writer(void *arg){
    int i = (int) arg;
    printf("Escritor %d criado\n", i);
 
    while(TRUE){
        think_up_data(i);
        printf("Escritor %d tentando escrever na região crítica\n", i);
        sem_wait(&db);
        write_data_base(i);
        printf("Escritor %d escreveu na região crítica\n", i);
        sem_post(&db);
    }
}
/* Função que representa a leitura da base de dados */
void read_data_base(int i){
    printf("Leitor %d lendo base de dados...\n", i);
    usleep(rand()%1500000);
}
/* Função que representa o processamento dos dados lidos */
void use_data_read(int i){
    printf("Leitor %d usou dados lidos\n", i);
    usleep(rand()%1500000);
}
/* Função que representa um processamento qualquer */
void think_up_data(int i){
    printf("Escritor %d em região não critica\n", i);
    usleep(rand()%1500000);
}
/* Função que representa a escrita na base de dados */
void write_data_base(int i){
    printf("Escritor %d escrevendo na região crítica\n", i);
    usleep(rand()%1500000);
}

TESTES

Devido a forma com que foi desenvolvido, o processa precisa receber um caractere para parar.

Teste 1: 2 escritores e 1 leitor
Teste 2: 2 escritores e 4 leitores
Teste 3: 4 escritores e 5 leitores

$ ./leitores_e_escritores 2 1
Leitor 0 criado
Leitor 0 tentando ler base de dados.
Leitor 0 lendo base de dados...
Escritor 0 criado
Escritor 0 em região não critica
Escritor 1 criado
Escritor 1 em região não critica
Escritor 1 tentando escrever na região crítica
Escritor 0 tentando escrever na região crítica
Leitor 0 leu base de dados.
Leitor 0 usou dados lidos
Escritor 1 escrevendo na região crítica
Leitor 0 tentando ler base de dados.
Escritor 1 escreveu na região crítica
Escritor 0 escrevendo na região crítica
Escritor 1 em região não critica
Escritor 0 escreveu na região crítica
Escritor 0 em região não critica
Leitor 0 lendo base de dados...
Escritor 1 tentando escrever na região crítica
Leitor 0 leu base de dados.
Leitor 0 usou dados lidos
Escritor 1 escrevendo na região crítica
Leitor 0 tentando ler base de dados.
Escritor 0 tentando escrever na região crítica
................................

$  ./leitores_e_escritores 2 4
Escritor 0 criado
Escritor 0 em região não critica
Escritor 1 criado
Escritor 1 em região não critica
Leitor 1 criado
Leitor 1 tentando ler base de dados.
Leitor 1 lendo base de dados...
Leitor 0 criado
Leitor 0 lendo base de dados...
Leitor 2 criado
Leitor 2 lendo base de dados...
Leitor 3 criado
Leitor 3 lendo base de dados...
Leitor 0 leu base de dados.
Leitor 0 usou dados lidos
Leitor 1 leu base de dados.
Leitor 1 usou dados lidos
Leitor 2 leu base de dados.
Leitor 2 usou dados lidos
Escritor 1 tentando escrever na região crítica
Escritor 0 tentando escrever na região crítica
Leitor 2 lendo base de dados...
Leitor 3 leu base de dados.
Leitor 3 usou dados lidos
Leitor 2 leu base de dados.
Leitor 2 usou dados lidos
Escritor 1 escrevendo na região crítica
Leitor 1 tentando ler base de dados.
........................................

$ Escritor 0 criado
Escritor 0 em região não critica
Escritor 1 criado
Escritor 1 em região não critica
Escritor 2 criado
Escritor 2 em região não critica
Escritor 3 criado
Escritor 3 em região não critica
Leitor 0 criado
Leitor 0 tentando ler base de dados.
Leitor 0 lendo base de dados...
Leitor 1 criado
Leitor 1 lendo base de dados...
Leitor 2 criado
Leitor 2 lendo base de dados...
Leitor 3 criado
Leitor 3 lendo base de dados...
Escritor 3 tentando escrever na região crítica
Escritor 2 tentando escrever na região crítica
Leitor 4 criado
Leitor 4 lendo base de dados...
Leitor 0 leu base de dados.
Leitor 0 usou dados lidos
Leitor 0 lendo base de dados...
Escritor 1 tentando escrever na região crítica
Leitor 0 leu base de dados.
Leitor 0 usou dados lidos
Escritor 0 tentando escrever na região crítica
Leitor 4 leu base de dados.
Leitor 4 usou dados lidos
............
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License