quinta-feira, 7 de maio de 2009

Problema dos Leitores e Escritores utilizando Mutex e Semáforos

O problema dos Leitores e Escritores trata a situação em que várias threads devem acessar a mesma memória compartilhada. Alguns para ler e outros para escrever.
Contudo, existem algumas restrições para realizarmos a leitura e escrita:
- Enquanto um processo estiver escrevendo, nenhum outro processo pode acessar este espaço de memória.
- Enquanto um processo estiver lendo, somente processos querendo ler podem acessar este espaço de memória.

Este problema pode ser abordado de várias formas. Em uma das abordagens, damos preferência ao escritor, ou seja, o escritor, uma vez desejando acesso à memória compartilhada, a obtém mesmo que processos leitores estivessem esperando antes.
Em outra abordagem, damos preferência aos leitores, ou seja, o escritor só obtem acesso à memória compartilhada quando um todos os escritores liberam o acesso. Esta situação é perigosa e pode levar a um starvation do escritor no caso em que temos vários processos leitores.

Em nossa solução, daremos preferência aos leitores.
Para aprender mais sobre este problema, visite: http://en.wikipedia.org/wiki/Readers-writers_problem

Além disso, nossa solução utiliza uma geração de valores randômicos para simular os tempos que o escritor levará para pensar no que irá escrever e o tempo que demora escrevendo na base de dados. E o consumidor terá valores randômicos para simular o tempo em que fica no banco de dados e o tempo em que fica processando as informações adquiridas.

Utilizaremos as instruções pthread_mutex_lock e pthread_mutex_unlock para controlar o acesso às regiões críticas. Documentação do uso pode ser encontrada em: http://www.opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_unlock.html
Para criar estes semáforos, vamos utilizar os seguintes comandos pthread_t e pthrad_mutex_init:
http://opengroup.org/onlinepubs/007908775/xsh/pthread_mutex_init.html


Além disso, devemos criar as threads. Isto pode ser feito utilizando os seguintes comandos:
declaração: pthread_t
criação: pthread_create() - http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_create.html

Aqui, é interessante notar que ao criarmos a thread, ela inicia sua execução. Contudo, a thread principal não pára sua execução! Assim, é necessário utilizarmos o comando pthread_join para evitar que a thread principal termine o programa, e com isso, mate todas as outras threads.
pthread_join() - http://www.opengroup.org/onlinepubs/007908799/xsh/pthread_join.html



Para compilar o programa e gerar o executável, utilizaremos:
gcc [[nome_programa.c]] -o [[nome_programa]] -lpthread
Para executar o programa criado, utilizaremos:
./[[nome_programa]]

Utilizamos o seguinte código:

//Bibliotecas utilizadas
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#include <semaphore.h>

#define READERS 20 //quantidade de leitores
#define WRITERS 3 //quantidade de escritores



pthread_mutex_t db; //exclusao mutua para regioes criticas... controla o acesso ao banco de dados
pthread_mutex_t mutex; //exclusao mutua para regioes cri­ticas... controla o acesso a variável rc
int rc; //quantidade de leitores lendo ou querendo ler a base de dados


// prototipos-------------------------------------

void read_data_base(void);
void
use_data_read(void);
void
think_up_data(void);

void
write_data_base(void);


void
reader() {
while
(1) { /* repete eternamente */

pthread_mutex_lock(&mutex); //down(&mutex); garante acesso exclusivo a variavelrc
rc=rc+1; //um novo leitor

if(rc==1) pthread_mutex_lock(&db); //caso este seja o primeiro leitor...
pthread_mutex_unlock(&mutex); //up(&mutex); libera o acesso a variavel rc

read_data_base(); //le a base de dados
pthread_mutex_lock(&mutex); //down(&mutex); garante acesso exclusivo a variavel rc
rc=rc-1; //um leitor a menos...

if(rc==0) pthread_mutex_unlock(&db); //caso este seja o ultimo leitor...
pthread_mutex_unlock(&mutex); //up(&mutex); libera o acesso a variavel rc

use_data_read(); //utiliza as informacoes da base de dados para algum trabalho...
}
}


void
writer() {

while
(1) //repete eternamente

{
think_up_data(); //pensa em informações para adicionar a base de dados
pthread_mutex_lock(&db); //down(&db); garante acesso exclusivo a base de dados
write_data_base(); //escreve novas informacoes na base de dados

pthread_mutex_unlock(&db); //up(&db); libera o acesso a base de dados
}
}


void
read_data_base()
{


/*quanto tempo o leitor permanecerá lendo a base de dados*/

int
readingtime;
readingtime = rand() % 3;

printf("Usuário lendo banco de dados. Total de %d leitores lendo agora.\n",rc);
sleep(readingtime);
}

void
use_data_read()
{


/*quanto tempo o leitor permanecerá utilizando os dados lidos*/

int
usetime;
usetime = rand() % 20;

printf("Usuário utilizando conhecimento adquirido no banco de dados\n");
sleep(usetime);
}

void
think_up_data()
{


/*quanto tempo o escritor gasta pensando no que irá escrever*/

int
thinktime;
thinktime = rand() % 10;

printf("Escritor pensando no que irá escrever\n");
sleep(thinktime);
}

void
write_data_base()
{


/*quanto tempo o escritor gasta escrevendo na base de dados*/

int
writetime;
writetime = rand() % 6;

printf("Escritor escrevendo no banco de dados\n");
sleep(writetime);
}



/////MAIN FUNCTION///////////////////////////////
main()
{


pthread_t writerthreads[WRITERS], readerthreads[READERS];
int
i;

//inicializacao dos semaforos...
pthread_mutex_init(&db, NULL);
pthread_mutex_init(&mutex, NULL);


//criação das threads independentes de escritores...
for(i=0;i<WRITERS;i++){
pthread_create( &writerthreads[i], NULL,(void *) writer, NULL);
}


//criação das threads independentes de leitores...
for(i=0;i<READERS;i++){
pthread_create( &readerthreads[i], NULL,(void *) reader, NULL);
}



for
(i=0;i<WRITERS;i++){
pthread_join(writerthreads[i], NULL);
}


for
(i=0;i<READERS;i++){
pthread_join(readerthreads[i], NULL);
}



exit(0);
}



Assim, obtivemos o seguinte resultado:
andersonaiziro@Aaiziro:~/Documents$ ./reader_writer
Escritor pensando no que irá escrever
Escritor pensando no que irá escrever
Escritor pensando no que irá escrever
Usuário lendo banco de dados. Total de 1 leitores lendo agora.
Usuário lendo banco de dados. Total de 2 leitores lendo agora.
Usuário lendo banco de dados. Total de 3 leitores lendo agora.
Usuário lendo banco de dados. Total de 4 leitores lendo agora.
Usuário lendo banco de dados. Total de 5 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 5 leitores lendo agora.
Usuário lendo banco de dados. Total de 6 leitores lendo agora.
Usuário lendo banco de dados. Total de 7 leitores lendo agora.
Usuário lendo banco de dados. Total de 8 leitores lendo agora.
Usuário lendo banco de dados. Total de 9 leitores lendo agora.
Usuário lendo banco de dados. Total de 10 leitores lendo agora.
Usuário lendo banco de dados. Total de 11 leitores lendo agora.
Usuário lendo banco de dados. Total de 12 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 12 leitores lendo agora.
Usuário lendo banco de dados. Total de 13 leitores lendo agora.
Usuário lendo banco de dados. Total de 14 leitores lendo agora.
Usuário lendo banco de dados. Total de 15 leitores lendo agora.
Usuário lendo banco de dados. Total de 16 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 16 leitores lendo agora.
Usuário lendo banco de dados. Total de 17 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Escritor escrevendo no banco de dados
Escritor pensando no que irá escrever
Usuário lendo banco de dados. Total de 1 leitores lendo agora.
Usuário lendo banco de dados. Total de 2 leitores lendo agora.
Usuário lendo banco de dados. Total de 3 leitores lendo agora.
Usuário lendo banco de dados. Total de 4 leitores lendo agora.
Usuário lendo banco de dados. Total de 5 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 5 leitores lendo agora.
Usuário lendo banco de dados. Total de 6 leitores lendo agora.
Usuário lendo banco de dados. Total de 7 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 5 leitores lendo agora.
Usuário lendo banco de dados. Total de 6 leitores lendo agora.
Usuário lendo banco de dados. Total de 7 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 3 leitores lendo agora.
Usuário lendo banco de dados. Total de 4 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 4 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 3 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Usuário utilizando conhecimento adquirido no banco de dados
Escritor escrevendo no banco de dados
Escritor pensando no que irá escrever
Escritor escrevendo no banco de dados
Escritor pensando no que irá escrever
Escritor escrevendo no banco de dados
Escritor pensando no que irá escrever
Usuário lendo banco de dados. Total de 1 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 1 leitores lendo agora.
Usuário lendo banco de dados. Total de 2 leitores lendo agora.
Usuário lendo banco de dados. Total de 3 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 3 leitores lendo agora.
Usuário lendo banco de dados. Total de 4 leitores lendo agora.
Usuário lendo banco de dados. Total de 5 leitores lendo agora.
Usuário lendo banco de dados. Total de 6 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 6 leitores lendo agora.
Usuário lendo banco de dados. Total de 7 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 7 leitores lendo agora.
Usuário lendo banco de dados. Total de 8 leitores lendo agora.
Usuário lendo banco de dados. Total de 9 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados
Usuário lendo banco de dados. Total de 9 leitores lendo agora.
Usuário lendo banco de dados. Total de 10 leitores lendo agora.
Usuário utilizando conhecimento adquirido no banco de dados

4 comentários:

  1. Como fazer com o que esse código para de ficar executando sem ter que clicar na tela do prompt para que ele pare de executar?

    ResponderExcluir
  2. Eu não sei se eu salvei essa página ou essa página que me salvou.

    ResponderExcluir
  3. Casino Review - DRMCD
    Casino Review. The gambling site has 안성 출장안마 a nice array of games available. 대구광역 출장마사지 We have selected the most popular games from the casino. 경상남도 출장안마 There are 광양 출장마사지 various 이천 출장샵 welcome bonuses  Rating: 4 · ‎Review by drmcd

    ResponderExcluir