Relatorio Labs CES-33

Objetivo

Aprender a manipular threads e semaforos no Linux, aplicando-os em problemas classicos relacionados ao assunto.

Problemas

A seguir quatro problemas classicos envolvendo threads e semaforos. Nao irei explicar muito a respeito dos codigos das solucoes, uma vez que estes foram retirados direamente do livro do Tanenbaum de sistemas operacionais, vou me concentrar nas ideias das solucoes e como criei as threads para resolver os problemas.

Problema do Jantar dos Filosofos

Imagine que filosofos apenas possuem duas acoes: comer e pensar. Imagine agoram que cinco filosofos dividem uma mesa com cinco pratos e cinco cadeiras para cada um sentar. No entanto, ha tambem apenas 5 talheres para eles dividirem, sendo que para comer cada filosofo necessita de dois talheres e eles so conseguem pegar os talheres que estao ao lado de seu prato.
Dessa forma, fica impossivel que dois filosofos que se sentam em cadeiras adjacentes comam ao mesmo tempo. Entao como resolver o problema? Se nao utilizarmos um algoritmo apropriado para organizar como os filosofos irao se alimentar, cada um pode pegar apenas um garfo e todos irao morrer de fome!

Solucao

A ideia da solucao e fazer com que cada filosofo, cada vez que for tentar comer, tente pegar os dois garfos de uma vez. Dessa forma, caso consiga, ele pode jantar e ao terminar deixa os dois talheres disponiveis; caso nao consiga, nao pega nenhum garfo, nao disperdicando apensa um garfo em sua mao. Depois de comer, o filosofo ira pensar, e em seguida comer, e depois pensar, e assim por diante.

O codigo para essa solucao e o seguinte:

#include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include<pthread.h>
 
#define N              5  
 
#define LEFT           (i+N-1)%N 
 
#define RIGHT          (i+1)%N
 
#define THINKING       0   
 
#define HUNGRY         1   
 
#define EATING         2  
 
int state[N];            
 
sem_t mutex;       
 
sem_t s[N];           
 
//prototipos
void philosopher (int i);
void take_forks(int i); 
void put_forks(int i); 
void test(int i);
void eat(int i);
void think(int i);
 
int main()
{
    sem_init(&mutex, 0, 1);
    sem_init(&s[0], 0, 0);
    sem_init(&s[1], 0, 0);
    sem_init(&s[2], 0, 0);
    sem_init(&s[3], 0, 0);
    sem_init(&s[4], 0, 0);
 
    pthread_t thread0, thread1, thread2, thread3, thread4;
 
    pthread_create(&thread0, NULL, (void*)philosopher, (int *)0);
    pthread_create(&thread1, NULL, (void*)philosopher, (int *)1);
    pthread_create(&thread2, NULL, (void*)philosopher, (int *)2);
    pthread_create(&thread3, NULL, (void*)philosopher, (int *)3);
    pthread_create(&thread4, NULL, (void*)philosopher, (int *)4);
 
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);
 
}
 
void philosopher (int i)   #include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include<pthread.h>
 
#define N              5  
 
#define LEFT           (i+N-1)%N 
 
#define RIGHT          (i+1)%N
 
#define THINKING       0   
 
#define HUNGRY         1   
 
#define EATING         2  
 
int state[N];            
 
sem_t mutex;       
 
sem_t s[N];           
 
//prototipos
void philosopher (int i);
void take_forks(int i); 
void put_forks(int i); 
void test(int i);
void eat(int i);
void think(int i);
 
int main()
{
    //inicializando os semaforos
    sem_init(&mutex, 0, 1);
    sem_init(&s[0], 0, 0);
    sem_init(&s[1], 0, 0);
    sem_init(&s[2], 0, 0);
    sem_init(&s[3], 0, 0);
    sem_init(&s[4], 0, 0);
 
    //declarando as threads
    pthread_t thread0, thread1, thread2, thread3, thread4;
 
    //criando uma thread para cada filosofo
    pthread_create(&thread0, NULL, (void*)philosopher, (int *)0);
    pthread_create(&thread1, NULL, (void*)philosopher, (int *)1);
    pthread_create(&thread2, NULL, (void*)philosopher, (int *)2);
    pthread_create(&thread3, NULL, (void*)philosopher, (int *)3);
    pthread_create(&thread4, NULL, (void*)philosopher, (int *)4);
 
    //para o programa nao terminar ate que as threads nao terminem
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);
 
}
 
void philosopher (int i)   
 
{
    int cont = 0;
 
    while (cont < 10) {         
 
        think(i);         
 
        take_forks(i);    
 
        eat(i);            
 
        put_forks(i);     
    cont++;
 
    }
 
}//inicializando os semaforos
 
void take_forks(int i)   
 
{
 
    sem_wait(&mutex);         
 
    state[i] = HUNGRY;    
 
    printf("Filosofo %d esta com fome\n",i);
 
    test(i);              
 
    sem_post(&mutex);        
 
    sem_wait(&s[i]);           
 
}
 
void put_forks(int i)        
 
{
 
    sem_wait(&mutex);        
 
    state[i] = THINKING;   
 
    printf("Filosofo %d esta pensando\n",i);
 
    test(LEFT);            
 
    test(RIGHT);        
 
    sem_post(&mutex);            
 
}
 
void test(int i)             
 
{
 
  if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) {
 
    state[i] = EATING;
 
    printf("Filosofo %d esta comendo\n",i);
 
    sem_post(&s[i]);
 
  }
 
}
 
void eat(int i)
{
    sleep(1);
}
 
void think(int i)
{
    sleep(1);
}
#include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include<pthread.h>
 
#define N              5  
 
#define LEFT           (i+N-1)%N 
 
#define RIGHT          (i+1)%N
 
#define THINKING       0   
 
#define HUNGRY         1   
 
#define EATING         2  
 
int state[N];            
 
sem_t mutex;       
 
sem_t s[N];           
 
//prototipos
void philosopher (int i);
void take_forks(int i); 
void put_forks(int i); 
void test(int i);
void eat(int i);
void think(int i);
 
int main()
{
    //inicializando os semaforos
    sem_init(&mutex, 0, 1);
    sem_init(&s[0], 0, 0);
    sem_init(&s[1], 0, 0);
    sem_init(&s[2], 0, 0);
    sem_init(&s[3], 0, 0);
    sem_init(&s[4], 0, 0);
 
    //declarando as threads
    pthread_t thread0, thread1, thread2, thread3, thread4;
 
    //criando uma thread para cada filosofo
    pthread_create(&thread0, NULL, (void*)philosopher, (int *)0);
    pthread_create(&thread1, NULL, (void*)philosopher, (int *)1);
    pthread_create(&thread2, NULL, (void*)philosopher, (int *)2);
    pthread_create(&thread3, NULL, (void*)philosopher, (int *)3);
    pthread_create(&thread4, NULL, (void*)philosopher, (int *)4);
 
    //para o programa nao terminar ate que as threads nao terminem
    pthread_join(thread0, NULL);
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);
    pthread_join(thread3, NULL);
    pthread_join(thread4, NULL);
 
}
 
void philosopher (int i)   
 
{
    int cont = 0;
 
    while (cont < 10) {         
 
        think(i);         
 
        take_forks(i);    
 
        eat(i);            
 
        put_forks(i);     
    cont++;
 
    }
 
}//inicializando os semaforos
 
void take_forks(int i)   
 
{
 
    sem_wait(&mutex);         
 
    state[i] = HUNGRY;    
 
    printf("Filosofo %d esta com fome\n",i);
 
    test(i);              
 
    sem_post(&mutex);        
 
    sem_wait(&s[i]);           
 
}
 
void put_forks(int i)        
 
{
 
    sem_wait(&mutex);        
 
    state[i] = THINKING;   
 
    printf("Filosofo %d esta pensando\n",i);
 
    test(LEFT);            
 
    test(RIGHT);        
 
    sem_post(&mutex);            
 
}
 
void test(int i)             
 
{
 
  if (state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING) {
 
    state[i] = EATING;
 
    printf("Filosofo %d esta comendo\n",i);
 
    sem_post(&s[i]);
 
  }
 
}
 
void eat(int i)
{
    sleep(1);
}
 
void think(int i)
{
    sleep(1);
}

Os sleeps foram utilizados para que uma thread nao percorra todas suas acoes muito rapidamente, permitindo que outras threads tenham acoes intercaladas com ela.

Depois de compilar o codigo acima, obteve-se o seguinte resultado:
Filosofo 0 esta com fome
Filosofo 0 esta comendo
Filosofo 1 esta com fome
Filosofo 2 esta com fome
Filosofo 2 esta comendo
Filosofo 3 esta com fome
Filosofo 4 esta com fome
Filosofo 2 esta pensando
Filosofo 3 esta comendo
Filosofo 0 esta pensando
Filosofo 1 esta comendo
Filosofo 1 esta pensando
Filosofo 3 esta pensando
Filosofo 4 esta comendo
Filosofo 2 esta com fome
Filosofo 2 esta comendo
Filosofo 0 esta com fome
Filosofo 1 esta com fome
Filosofo 2 esta pensando
Filosofo 1 esta comendo
Filosofo 3 esta com fome
Filosofo 4 esta pensando
Filosofo 3 esta comendo
Filosofo 1 esta pensando
Filosofo 0 esta comendo
Filosofo 3 esta pensando
Filosofo 4 esta com fome
Filosofo 2 esta com fome
Filosofo 2 esta comendo
Filosofo 3 esta com fome
Filosofo 2 esta pensando
Filosofo 3 esta comendo
Filosofo 0 esta pensando
Filosofo 1 esta com fome
Filosofo 1 esta comendo
Filosofo 3 esta pensando
Filosofo 4 esta comendo
Filosofo 0 esta com fome
Filosofo 1 esta pensando
Filosofo 2 esta com fome
Filosofo 2 esta comendo
Filosofo 4 esta pensando
Filosofo 0 esta comendo
Filosofo 1 esta com fome
Filosofo 3 esta com fome
Filosofo 2 esta pensando
Filosofo 3 esta comendo
Filosofo 0 esta pensando
Filosofo 1 esta comendo
Filosofo 3 esta pensando
Filosofo 2 esta com fome
Filosofo 4 esta com fome
Filosofo 4 esta comendo
Filosofo 0 esta com fome
Filosofo 1 esta pensando
Filosofo 2 esta comendo
Filosofo 3 esta com fome
Filosofo 4 esta pensando
Filosofo 0 esta comendo
Filosofo 0 esta pensando
Filosofo 2 esta pensando
Filosofo 3 esta comendo
Filosofo 4 esta com fome
Filosofo 1 esta com fome
Filosofo 1 esta comendo
Filosofo 3 esta pensando
Filosofo 4 esta comendo
Filosofo 2 esta com fome
Filosofo 0 esta com fome
Filosofo 1 esta pensando
Filosofo 2 esta comendo
Filosofo 4 esta pensando
Filosofo 0 esta comendo
Filosofo 2 esta pensando
Filosofo 3 esta com fome
Filosofo 3 esta comendo
Filosofo 1 esta com fome
Filosofo 2 esta com fome
Filosofo 4 esta com fome
Filosofo 3 esta pensando
Filosofo 2 esta comendo
Filosofo 0 esta pensando
Filosofo 4 esta comendo
Filosofo 4 esta pensando
Filosofo 3 esta com fome
Filosofo 0 esta com fome
Filosofo 0 esta comendo
Filosofo 2 esta pensando
Filosofo 3 esta comendo
Filosofo 0 esta pensando
Filosofo 1 esta comendo
Filosofo 3 esta pensando
Filosofo 2 esta com fome
Filosofo 4 esta com fome
Filosofo 4 esta comendo
Filosofo 3 esta com fome
Filosofo 4 esta pensando
Filosofo 3 esta comendo
Filosofo 1 esta pensando
Filosofo 0 esta com fome
Filosofo 0 esta comendo
Filosofo 3 esta pensando
Filosofo 2 esta comendo
Filosofo 1 esta com fome
Filosofo 4 esta com fome
Filosofo 0 esta pensando
Filosofo 4 esta comendo
Filosofo 3 esta com fome
Filosofo 4 esta pensando
Filosofo 2 esta pensando
Filosofo 1 esta comendo
Filosofo 3 esta comendo
Filosofo 0 esta com fome
Filosofo 1 esta pensando
Filosofo 0 esta comendo
Filosofo 3 esta pensando
Filosofo 4 esta com fome
Filosofo 2 esta com fome
Filosofo 2 esta comendo
Filosofo 3 esta com fome
Filosofo 2 esta pensando
Filosofo 3 esta comendo
Filosofo 0 esta pensando
Filosofo 1 esta com fome
Filosofo 1 esta comendo
Filosofo 0 esta com fome
Filosofo 2 esta com fome
Filosofo 1 esta pensando
Filosofo 0 esta comendo
Filosofo 3 esta pensando
Filosofo 2 esta comendo
Filosofo 0 esta pensando
Filosofo 4 esta comendo
Filosofo 1 esta com fome
Filosofo 2 esta pensando
Filosofo 1 esta comendo
Filosofo 0 esta com fome
Filosofo 4 esta pensando
Filosofo 1 esta pensando
Filosofo 0 esta comendo
Filosofo 1 esta com fome
Filosofo 4 esta com fome
Filosofo 0 esta pensando
Filosofo 4 esta comendo
Filosofo 1 esta comendo
Filosofo 4 esta pensando
Filosofo 1 esta pensando
Filosofo 4 esta com fome
Filosofo 4 esta comendo
Filosofo 4 esta pensando

Observe que nunca temos dois filosofos adjacentes comendo, o que nos mostra a eficacia da solucao.

Problema da Barbearia

Imagine uma barbearia com 5 cadeiras para os clientes dormirem para esperar enquanto o barbeiro esta ocupado. Quando um cliente chega e todas as cadeiras estao lotadas, ele nao espera e vai embora. Por outro lado, se nao tem nenhum cliente na barbearia, o barbeiro dorme. Dai, quando o primeiro cliente chegar, este o acorda para cortar seu cabelo. Como implementar este problema?

Solucao

A ideia e manter um contador waiting de quantas pessoas estao esperando o barbeiro, se ja possuem 5 e um outro cliente chega, este deixa a barbearia sem ser atendido.

O codigo com a solucao do problema eh o seguinte:

#include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include<pthread.h>
 
#define CHAIRS 5               /* # cadeiras para os clientes */
#define TRUE 1
 
sem_t customers;       /* # de clientes esperando o barbeiro */
 
sem_t barbers;         /* para o barbeiro */
 
sem_t mutex;           /* para exclusao mutua */
 
int waiting = 0;               /* # de clientes esperando */
 
//prototipos
void barber(void);
void customer(int i);
void get_haircut(int i);
void cut_hair(void);
 
int main()
{
    //inicializando os semaforos
    sem_init(&mutex, 0, 1);
    sem_init(&customers, 0, 0);
    sem_init(&barbers, 0, 0);
 
    //declarando as threads
    pthread_t thr_customer[35];
    pthread_t thr_barber;
 
    //criando a thread do barbeiro
    pthread_create(&thr_barber, NULL, (void*)barber, NULL);
 
    //criando uma thread para cada cliente
    int i;
    for(i=0; i<35; i++)
    {
        pthread_create(&thr_customer[i], NULL, (void*)customer, (int *)i);
        if(i==6) sleep(3);                //os sleeps foram utilizados para controlar
        if(i==11)sleep(8);                //quando cada cliente tentar entrar na barbearia
        if(i==24)sleep(4);
        if(i==27)sleep(3);
        if(i==33)sleep(4);
    }
 
    //para o programa nao terminar ate que a thread do barbeiro termine,
    //o que naum ira acontecer pois esta num loop infinito
    pthread_join(thr_barber, NULL);       
}
 
void barber(void)
 
{
 
    while (TRUE) {
    if(waiting == 0)
        printf("Nenhum cliente... entao Barbeiro foi dormir!!\n");
 
        sem_wait(&customers);      /* dorme se # de clientes eh zero */
 
        sem_wait(&mutex);          /* acesso para waiting */
 
        waiting = waiting - 1; /* decrementa # de clientes esperando */
 
        sem_post(&barbers);          /* barbeiro pronto para cortar */
 
        sem_post(&mutex);            /* libera waiting 'waiting' */
 
        cut_hair();            /* corta cabelo */
 
    }
 
}
 
void customer(int i)
 
{
 
    sem_wait(&mutex);              /* entra na regiao critica */
 
    if (waiting < CHAIRS) {    /* verifica se possue cadeiras livres */
    printf("Cliente %d entra na barbearia...\n",i);
 
        waiting = waiting + 1; 
 
        sem_post(&customers);        /* acorda barbeiro se necessario */
 
        sem_post(&mutex);            /* libera waiting */
 
        sem_wait(&barbers);        /* dorme se # de barbeiro eh zero */
 
        get_haircut(i);         /* senta e corta o cabelo */
 
    } else {
    printf("Barbearia lotada! Cliente %d desiste de cortar cabelo...\n",i);
 
        sem_post(&mutex);            /* barbearia lotada, cliente nao entra */
 
    }
 
}
 
void get_haircut(int i)
{
    printf("Cliente %d cortando cabelo\n",i);
 
    sleep(1);
 
}
 
void cut_hair(void)
{
 
    sleep(1);
 
}

Os sleeps possuem o mesmo intuito que no problema anterior.

Observe que na hora de criar as threads para os clientes, nao os criei todos juntos, pois se o fizesse seria como se todos os clientes tentassem entrar juntos na barbearia, sendo que soh o 6 primeiros iriam relamente ser atendidos (os outros deixariam a barbearia por estar lotada!). Para isso nao acontecer, controlei o tempo de forma que vissemos as diversas possibilidades do problema: barbeiro durmindo pois nenhum cleinte havia chegado, 7 clientes chegando juntos (sendo que o ultimo desiste de cortar cabelo pois as cadeiras estao preenchidas), clientes chegando depois que alguns clientes jah haviam cortado o cabelo (mas nao todos os cinco que estavam esperando) etc.

As respostas obtidas foram as seguintes:
Nenhum cliente… entao Barbeiro foi dormir!!
Cliente 0 entra na barbearia…
Cliente 0 cortando cabelo
Cliente 1 entra na barbearia…
Cliente 2 entra na barbearia…
Cliente 3 entra na barbearia…
Cliente 4 entra na barbearia…
Cliente 5 entra na barbearia…
Barbearia lotada! Cliente 6 desiste de cortar cabelo…
Cliente 1 cortando cabelo
Cliente 2 cortando cabelo
Cliente 3 cortando cabelo
Cliente 7 entra na barbearia…
Cliente 9 entra na barbearia…
Cliente 8 entra na barbearia…
Barbearia lotada! Cliente 10 desiste de cortar cabelo…
Barbearia lotada! Cliente 11 desiste de cortar cabelo…
Cliente 4 cortando cabelo
Cliente 5 cortando cabelo
Cliente 7 cortando cabelo
Cliente 8 cortando cabelo
Cliente 9 cortando cabelo
Nenhum cliente… entao Barbeiro foi dormir!!
Cliente 12 entra na barbearia…
Cliente 12 cortando cabelo
Cliente 13 entra na barbearia…
Cliente 14 entra na barbearia…
Cliente 15 entra na barbearia…
Cliente 16 entra na barbearia…
Cliente 17 entra na barbearia…
Barbearia lotada! Cliente 18 desiste de cortar cabelo…
Barbearia lotada! Cliente 19 desiste de cortar cabelo…
Barbearia lotada! Cliente 20 desiste de cortar cabelo…
Barbearia lotada! Cliente 21 desiste de cortar cabelo…
Barbearia lotada! Cliente 22 desiste de cortar cabelo…
Barbearia lotada! Cliente 23 desiste de cortar cabelo…
Barbearia lotada! Cliente 24 desiste de cortar cabelo…
Cliente 13 cortando cabelo
Cliente 14 cortando cabelo
Cliente 15 cortando cabelo
Cliente 16 cortando cabelo
Cliente 25 entra na barbearia…
Cliente 26 entra na barbearia…
Cliente 27 entra na barbearia…
Cliente 17 cortando cabelo
Cliente 25 cortando cabelo
Cliente 26 cortando cabelo
Cliente 28 entra na barbearia…
Cliente 29 entra na barbearia…
Cliente 30 entra na barbearia…
Cliente 31 entra na barbearia…
Barbearia lotada! Cliente 32 desiste de cortar cabelo…
Barbearia lotada! Cliente 33 desiste de cortar cabelo…
Cliente 27 cortando cabelo
Cliente 28 cortando cabelo
Cliente 29 cortando cabelo
Cliente 30 cortando cabelo
Cliente 34 entra na barbearia…
Cliente 31 cortando cabelo
Cliente 34 cortando cabelo
Nenhum cliente… entao Barbeiro foi dormir!!

Como pode-se observar, nunca temos mais de 6 clientes na barbearia (1 cortando o cabelo e 5 esperando), e quando nao se tem nenhum cliente, o barbeiro dorme, o que nos mostra a eficacia da solucao apresentada pelo codigo acima.

Problema dos Leitores e Escritores

Imagine que temos um documento que pode ser lido por varios leitores e tambem pode ser modificado por varios escritores. Pode haver diversos leitores vendo o documento ao mesmo tempo, mas para que um escritor faca uma mudanca no documento, nenhum outro escritor ou leitor pode estar com o documento aberto. Como implementar este problema usando threads?

Solucao

Se um escritor ficasse esperando todos os leitores deixarem o documento para so entao ele poder modifica-lo, o escritor poderia ficar esperando um longo tempo para faze-lo: imagine que chegue um leitor novo a cada 5 segundos e cada um demore mais de 5 segundos para ler o documento, o escritor nao iria conseguir modificar o documento nunca! Para resolver este problema, o codigo abaixo faz com que todos os leitores que chegarem depois de um escritor tenham que esperar este escrever no arquivo para so entao eles poderem ler. Dessa forma, nao obtemos a melhor eficiencia em termos de numero de threads que abriram o documento em um determinado tempo, mas pelo menos nenhuma thread pode ficar esperando infinitamente para ter acesso ao documento.

O codigo segue abaixo:

#include<stdio.h>
#include<semaphore.h>
#include<stdlib.h>
#include<pthread.h>
 
#define TRUE 1
 
//prototipos
void reader(int i);
void writer(int i);
void use_data_read(void);
void read_data_base(int i);
void think_up_data(int i);
void write_data_base(int i);
 
sem_t mutex;           
 
sem_t db;             
 
int rc = 0;                    
 
int main()
{
    //inicializando os semaforos
    sem_init(&mutex, 0, 1);
    sem_init(&db, 0, 1);
 
    //declarando as threads
    pthread_t th_writer[3];
    pthread_t th_reader[10];
 
    int i;
 
    //criando uma thread para cada escritor
    for(i=0; i<3; i++)
    {
        pthread_create(&th_writer[i], NULL, (void*)writer, (int *)i);
    }
 
    //criando uma thread para cada leitor
    for(i=0; i<10; i++)
    {
        pthread_create(&th_reader[i], NULL, (void*)reader, (int *)i);
    }
 
    //para o programa nao terminar ate que as threads nao terminem
    pthread_join(th_writer[0], NULL);
 
    return 0;
} 
 
void reader(int i)
 
{
 
    while (TRUE) {            
        printf("Leitor %d quer ler...\n",i);
 
        sem_wait(&mutex);        
 
        rc = rc + 1;         
 
        if (rc == 1) sem_wait(&db);   
 
        sem_post(&mutex);         
 
        read_data_base(i);    
 
        sem_wait(&mutex);      
 
        rc = rc - 1;          
 
        if (rc == 0) sem_post(&db);  
 
        sem_post(&mutex);           
 
        use_data_read();      
 
    }
 
}
 
void writer(int i)
 
{
 
    while (TRUE) {      
 
        think_up_data(i);   
 
        sem_wait(&db);             
 
        write_data_base(i);     
 
        sem_post(&db);           
 
    }
 
}
 
void use_data_read(void)
{
    sleep(1);
}
 
void read_data_base(int i)
{
    sleep(1);
    printf("Leitor %d le documento!\n",i);    
}
 
void think_up_data(int i)
{
    printf("Escritor %d quer escrever...\n",i);
}
 
void write_data_base(int i)
{
    sleep(1);
    printf("Escritor %d escreve no documento!\n",i);
}

Novamente, os sleeps foram criados com os mesmos propositos das questoes anteriores.

As respostas obtidas foram as seguintes:
Escritor 1 quer escrever…
Escritor 0 quer escrever…
Leitor 0 quer ler…
Escritor 2 quer escrever…
Leitor 1 quer ler…
Leitor 2 quer ler…
Leitor 3 quer ler…
Leitor 4 quer ler…
Leitor 5 quer ler…
Leitor 6 quer ler…
Leitor 7 quer ler…
Leitor 8 quer ler…
Leitor 9 quer ler…
Escritor 1 escreve no documento!
Escritor 1 quer escrever…
Escritor 1 escreve no documento!
Escritor 1 quer escrever…
Escritor 2 escreve no documento!
Escritor 2 quer escrever…
Leitor 4 le documento!
Leitor 0 le documento!
Leitor 5 le documento!
Leitor 1 le documento!
Leitor 6 le documento!
Leitor 3 le documento!
Leitor 7 le documento!
Leitor 8 le documento!
Leitor 2 le documento!
Leitor 9 le documento!
Leitor 5 quer ler…
Leitor 7 quer ler…
Leitor 2 quer ler…
Leitor 9 quer ler…
Leitor 6 quer ler…
Escritor 0 escreve no documento!
Leitor 8 quer ler…
Leitor 3 quer ler…
Leitor 4 quer ler…
Leitor 1 quer ler…
Leitor 0 quer ler…
Escritor 0 quer escrever…
Escritor 1 escreve no documento!
Escritor 1 quer escrever…
Escritor 2 escreve no documento!
Escritor 2 quer escrever…
Leitor 6 le documento!
Leitor 5 le documento!
Leitor 3 le documento!
Leitor 1 le documento!
Leitor 0 le documento!
Leitor 8 le documento!
Leitor 4 le documento!
Leitor 2 le documento!
Leitor 9 le documento!
Leitor 7 le documento!

Note que quando um leitor le o documento, todos os outros leitores tambem poderao le-lo, no entanto, caso chegue algum escritor, todos os leitores que chegaram depois dele irao espera-lo para poder ler o documento. Um escritor fica com o documento aberto sozinho. Isso tudo mostra a eficacia da solucao.

Conclusao

Com estes problemas classicos sobre threads e semaforos foi possivel obter um conhecimento bem mais concreto sobre os assuntos. De fato, mesmo tendo estudado teoricamente cada um dos problemas, nao sabia direito como implementar as solucoes, uma vez que nunca tinha aberto o Linux na minha vida! Alem de nao ter familiaridade com os comandos para semaforo e threads.
Para realizar as solucoes desses problemas, era imprescindivel que o aluno entendesse as solucoes para saber como fazer os testes, por isso considero acredito que foi importante a realizacao desses labs para a compreensao dos assuntos.

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