Laboratorio de CES-33: Pedro Cau

Problema 2: Jantar dos Filosofos

Temos uma mesa redonda com 5 cadeiras, 5 pratos e 5 garfos, com os pratos intercalados com os garfos. Há 5 filosofos que vivem de pensar e comer, porem para comer cada filosofo necessita de 2 garfos. Quando um filoso senta-se na mesa, este pega o garfo a sua esquerda , pega o da sua direita e entao inicia a refeiçao. O problema acontece quando os 5 filosofos resolvem sentar na mesa ao mesmo tempo, pegam o garfo a sua esquerda e não conseguem pegar o garfo a sua direita por que já foram pegos por outro filosofo, ficando entao esperando eternamente.

A implementaçao deste problema mostrada abaixo simula o dia-a-dia do filosofo sem deixar que o problema citado acima aconteça:

/* 
 * File:   filosofos.c
 * Author: pedro
 *
 * Created on May 6, 2009, 2:54 AM
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
 
#define N 5
#define LEFT (i-1+N)%N
#define RIGHT (i+1+N)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
 
int state[N];
sem_t mutex, philophore[N];
pthread_t philosopher[N];
 
char * getName(int id)
{
    switch(id)
    {
        case 0:
            return "5-Jandateles";
        case 1:
            return "1-Platao";
        case 2:
            return "2-Aristoteles";
        case 3:
            return "3-Socrates";
        case 4:
            return "4-Ptolomeu";
    }
}
 
void printStates()
{
    char* st[] = {"THINK ","HUNGRY","EATING"};
    printf("|%s|%s|%s|%s|%s|\n",st[state[0]],
                                st[state[1]],
                                st[state[2]],
                                st[state[3]],
                                st[state[4]]);
}
 
void test(i)
{
 
    if(state[i] == HUNGRY && state[LEFT]!= EATING && state[RIGHT] != EATING)
    {
        state[i] = EATING;
        sem_post(&philophore[i]);
    }
    if( state[RIGHT]== EATING && state[LEFT]== EATING)  printf("ph %s: %s",getName(i),"Os dois garfos ocupados\n");
    else if( state[LEFT]== EATING)  printf("ph %s: %s",getName(i),"Garfo esquerdo ocupado\n");
    else if( state[RIGHT]== EATING)  printf("ph %s: %s",getName(i),"Garfo direito ocupado\n");
    printStates();
}
 
void take_forks(int i)
{
    /********/sem_wait(&mutex);/*********/
    /**       Regiao Critica           **/
    /**/      state[i]= HUNGRY;       /**/
    /**/ printf("ph %s: %s",          /**/
    /**/ getName(i),"Com fome\n");    /**/
    /**/      test(i);                /**/
    /********/sem_post(&mutex);/*********/
 
    sem_wait(&philophore[i]);
}
 
void put_forks(int i)
{
    /********/sem_wait(&mutex);/*********/
    /**       Regiao Critica           **/
    /**/      state[i]= THINKING;     /**/
    /**/      test(LEFT);             /**/
    /**/      test(RIGHT);            /**/
    /********/sem_post(&mutex);/*********/
}
 
void think(int id)
{
    double time = drand48();
    printf("ph %s: %s",getName(id),"Filosofando\n");
    time = (4.0f+3.0f*time)*1000000.0f;
    usleep((int)time);
    printf("ph %s: %s",getName(id),"Elaborei uma nova teoria, estou feliz\n");
}
void eat(int id)
{
    double time = drand48();
    printf("ph %s: %s",getName(id),"Comendo\n");
    time = (4.0f+3.0f*time)*1000000.0f;
    usleep((int)time);
    printf("ph %s: %s",getName(id),"Estou satisfeito\n");
}
 
void *philosopherAct(void *i)
{
    while(1)
    {
      //  sleep(1);
        int id = *((int*)i);
        think(id);
      //  sleep(1);
        take_forks(id);
      //  sleep(1);
        eat(id);
      //  sleep(1);
        put_forks(id);
 
    }
}
 
int main(int argc, char** argv)
{
    srand48(time(NULL));
    sem_init(&mutex,0,1);
    int id[N]; 
    int i;
    for(i=0;i<N;++i)
    {
        sem_init(&philophore[i],0,0);
        id[i]=i;
        pthread_create(&philosopher[i],NULL,philosopherAct,(void*)&id[i]);
    }
 
    printf("Philosophers created\n");
    pthread_join(philosopher[0],NULL);
 
    printf("Fim");
    return (EXIT_SUCCESS);
}

Quando um filoso senta-se na me Ao se compilar e executar o programa acima, foi obtida a seguinte saida:

ph 5-Jandateles: Filosofando
ph 1-Platao: Filosofando
ph 2-Aristoteles: Filosofando
ph 3-Socrates: Filosofando
ph 4-Ptolomeu: Filosofando
Philosophers created
ph 3-Socrates: Elaborei uma nova teoria, estou feliz
ph 3-Socrates: Com fome
|THINK |THINK |THINK |EATING|THINK |
ph 3-Socrates: Comendo
ph 2-Aristoteles: Elaborei uma nova teoria, estou feliz
ph 2-Aristoteles: Com fome
ph 2-Aristoteles: Garfo direito ocupado
|THINK |THINK |HUNGRY|EATING|THINK |
ph 4-Ptolomeu: Elaborei uma nova teoria, estou feliz
ph 4-Ptolomeu: Com fome
ph 4-Ptolomeu: Garfo esquerdo ocupado
|THINK |THINK |HUNGRY|EATING|HUNGRY|
ph 5-Jandateles: Elaborei uma nova teoria, estou feliz
ph 5-Jandateles: Com fome
|EATING|THINK |HUNGRY|EATING|HUNGRY|
ph 5-Jandateles: Comendo
ph 1-Platao: Elaborei uma nova teoria, estou feliz
ph 1-Platao: Com fome
ph 1-Platao: Garfo esquerdo ocupado
|EATING|HUNGRY|HUNGRY|EATING|HUNGRY|
ph 3-Socrates: Estou satisfeito
ph 2-Aristoteles: Comendo
|EATING|HUNGRY|EATING|THINK |HUNGRY|
ph 4-Ptolomeu: Garfo direito ocupado
|EATING|HUNGRY|EATING|THINK |HUNGRY|
ph 3-Socrates: Filosofando
ph 5-Jandateles: Estou satisfeito
|THINK |HUNGRY|EATING|THINK |EATING|
ph 1-Platao: Garfo direito ocupado
|THINK |HUNGRY|EATING|THINK |EATING|
ph 5-Jandateles: Filosofando
ph 4-Ptolomeu: Comendo
ph 3-Socrates: Elaborei uma nova teoria, estou feliz
ph 3-Socrates: Com fome
ph 3-Socrates: Os dois garfos ocupados
|THINK |HUNGRY|EATING|HUNGRY|EATING|
ph 5-Jandateles: Elaborei uma nova teoria, estou feliz
ph 5-Jandateles: Com fome
ph 5-Jandateles: Garfo esquerdo ocupado
|HUNGRY|HUNGRY|EATING|HUNGRY|EATING|
ph 2-Aristoteles: Estou satisfeito
ph 1-Platao: Comendo
|HUNGRY|EATING|THINK |HUNGRY|EATING|
ph 3-Socrates: Garfo direito ocupado
|HUNGRY|EATING|THINK |HUNGRY|EATING|
ph 2-Aristoteles: Filosofando
ph 4-Ptolomeu: Estou satisfeito
ph 3-Socrates: Comendo
|HUNGRY|EATING|THINK |EATING|THINK |
ph 5-Jandateles: Garfo direito ocupado
|HUNGRY|EATING|THINK |EATING|THINK |
ph 4-Ptolomeu: Filosofando
ph 3-Socrates: Estou satisfeito
ph 2-Aristoteles: Garfo esquerdo ocupado
|HUNGRY|EATING|THINK |THINK |THINK |
|HUNGRY|EATING|THINK |THINK |THINK |
ph 3-Socrates: Filosofando
ph 4-Ptolomeu: Elaborei uma nova teoria, estou feliz
ph 4-Ptolomeu: Com fome
|HUNGRY|EATING|THINK |THINK |EATING|

Ao se observar a saida acima pode-ser notar que nunca dois filosofos em posicoes adjacentes estao comendo ao mem tempo.

Problema 3 : Problema do Barbeiro Adormecido

Temos uma barbearia com um barbeiro e um certo numero de cadeiras (no exemplo, 5 cadeiras). Quando não há clientes o barbeiro aproveita pra dormir ate que algum cliente apareca. Já o cliente quando chega verifica disponibilidade das cadeiras, caso não haja , este vai embora, caso contrario senta e espera a vez, indo embora somente apos ter o cablo cortado.

Temos abaixo a implementacao deste problema usando semaphores e mutexes.

/* 
 * File:   barber.c
 * Author: pedro
 *
 * Created on May 6, 2009, 3:01 PM
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
 
#define CADEIRAS 5
 
#define Init pthread_mutex_init
#define Lock pthread_mutex_lock
#define Unlock pthread_mutex_unlock
 
sem_t customers,barbers;
pthread_mutex_t mutex;
 
int waiting=0;
 
void cortar_cabelo()
{
    printf("Barber: Vour cortar o cabelo de mais um cliente\n");
 
    double time = drand48();
    time = (3.0f+1.0f*time)*1000000.0f;
    usleep((int)time);
    printf("Fila: %d\n",waiting);
}
 
void senta_e_seja_atendido(int i)
{
    printf("Cliente %d : Oba, vou ter o meu cabelo cortado\n",i);
}
 
void * barber(void * arg)
{
    while(1)
    {
        if(waiting == 0)printf("Barber: nao tem ninguem, vou dormir\n");
        sem_wait(&customers);
        Lock(&mutex);
        --waiting;
        sem_post(&barbers);
        Unlock(&mutex);
 
        cortar_cabelo();
    }
}
 
void * cliente(void * arg)
{
    int i = *(int*)arg;
    printf("Cliente %d: Cheguei na barbearia --  Fila: %d\n",i,waiting);
    Lock(&mutex);
    if(waiting< CADEIRAS)
    {
        ++waiting;
        sem_post(&customers);
        Unlock(&mutex);
        sem_wait(&barbers);
        senta_e_seja_atendido(i);
    }
    else
    {
        Unlock(&mutex);
        printf("Cliente %d: Ta lotada,Tchau!\n",i);
    }
}
 
int main(int argc, char** argv)
{
    srand48(time(NULL));
    printf("Inicio\n");
    sem_init(&customers,0,0);
    sem_init(&barbers,0,0);
    Init(&mutex,NULL);
    pthread_t barberThread;
    pthread_t *clientesThread;
 
    pthread_create(&barberThread,NULL,barber,NULL);
 
    int i = 1;
    while(1)
    {
        clientesThread = malloc(sizeof(pthread_t));
        pthread_create(clientesThread,NULL,cliente,(void *)&i);
 
        double time = drand48();
        time = (1.0f+1.0f*time)*1000000.0f;
        usleep((int)time);
 
        i++;
    }
    return 0;
}

Apos executar o programa foi obtida a seguinte saida:

Inicio
Barber: nao tem ninguem, vou dormir
Cliente 1: Cheguei na barbearia — Fila: 0
Barber: Vour cortar o cabelo de mais um cliente
Cliente 1 : Oba, vou ter o meu cabelo cortado
Cliente 2: Cheguei na barbearia — Fila: 0
Cliente 3: Cheguei na barbearia — Fila: 1
Cliente 4: Cheguei na barbearia — Fila: 2
Cliente 5: Cheguei na barbearia — Fila: 3
Fila: 4
Barber: Vour cortar o cabelo de mais um cliente
Cliente 4 : Oba, vou ter o meu cabelo cortado
Cliente 6: Cheguei na barbearia — Fila: 3
Cliente 7: Cheguei na barbearia — Fila: 4
Cliente 8: Cheguei na barbearia — Fila: 5
Cliente 8: Ta lotada,Tchau!
Cliente 9: Cheguei na barbearia — Fila: 5
Cliente 9: Ta lotada,Tchau!
Cliente 10: Cheguei na barbearia — Fila: 5
Cliente 10: Ta lotada,Tchau!
Fila: 5

Podemos ver que o programa esta funcionando, pois a fila nunca fica maior que 5 (o numero de cadeiras) e o babeiro continuamente cortando, ou dormindo caso não haja clientes.

Problema 4 Leitores e Escritores

Temos um banco de dados, quem pode ser escrito ou lido. Quando um thread esta lendo,outros threads podem ler tambem. Porem quando um thread esta escrevendo no banco de dados, nenhum outro thread possui acesso.

A soluçao implementada para esse problema esta a seguir:

/* 
 * File:   rw.c
 * Author: pedro
 *
 * Created on May 6, 2009, 11:07 AM
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
 
#define N 4
#define M 2
#define Init pthread_mutex_init
#define Lock pthread_mutex_lock
#define Unlock pthread_mutex_unlock
 
pthread_mutex_t mutex, db;
int rc = 0;
 
void ler_banco_de_dados(int id)
{
    printf("leitor %d: lendo banco de dados ^\n",id);
 
    double time = drand48();
    time = (2.0f+2.0f*time)*1000000.0f;
    usleep((int)time);
    printf("leitor %d: termino da leitura banco de dados v\n",id);
}
void usar_dados(int id)
{
    printf("leitor %d: usando dados\n",id);
 
    double time = drand48();
    time = (4.0f+5.0f*time)*1000000.0f;
    usleep((int)time);
}
 
void criar_dados(int id)
{
    printf("escritor %d: criando dados\n",id);
 
    double time = drand48();
    time = (2.0f+1.0f*time)*1000000.0f;
    usleep((int)time);
}
 
void escrever_banco_de_dados(int id)
{
    printf("escritor %d: escrevendo no banco de dados ^\n",id);
 
    double time = drand48();
    time = (4.0f+3.0f*time)*1000000.0f;
    usleep((int)time);
    printf("escritor %d: termino da escrita no banco de dados v\n",id);
}
 
void *reader(void *i)
{
    int id = *(int*)i;
    while(1)
    {
        Lock(&mutex);/*----------------*/
        rc++;                         // Area Critica
/*----*/if(rc==1)Lock(&db);           //
/**/    Unlock(&mutex);/*-------------*/
/**/    ler_banco_de_dados(id);
/**/    Lock(&mutex);/*---------------*/
/**/    --rc;                         // Area critica
/*----*/if(rc==0)Unlock(&db);         //
        Unlock(&mutex);/*-------------*/
        usar_dados(id);
    }
}
 
void *writer(void *i)
{
 
    int id = *(int*)i;
    while(1)
    {
        criar_dados(id);
        Lock(&db);/*-----------------*/
        escrever_banco_de_dados(id);   // Area critica
        Unlock(&db);/*---------------*/
 
    }
}
 
int main(int argc, char** argv)
{
    srand48(time(NULL));
    Init(&mutex,NULL);
    Init(&db,NULL);
 
    pthread_t readerThread[N],writerThread[M];
    int i;
    int id[N];
 
    printf("stating\n");
    for(i=0;i<N;++i)
    {
        id[i]=i+1;
        pthread_create(&readerThread[i],NULL,reader,(void*)&id[i]);
    }
    for(i=0;i<M;++i)
    {
        id[i]=i+1;
        pthread_create(&writerThread[i],NULL,writer,(void*)&id[i]);
    }
 
    sleep(35);
 
    return (EXIT_SUCCESS);
}

Ao exectar, se obteve o seguinte:

stating
leitor 2: lendo banco de dados ^
leitor 1: lendo banco de dados ^
leitor 3: lendo banco de dados ^
leitor 4: lendo banco de dados ^
escritor 1: criando dados
escritor 2: criando dados
leitor 4: termino da leitura banco de dados v
leitor 4: usando dados
leitor 1: termino da leitura banco de dados v
leitor 1: usando dados
leitor 2: termino da leitura banco de dados v
leitor 2: usando dados
leitor 3: termino da leitura banco de dados v
escritor 1: escrevendo no banco de dados ^
leitor 3: usando dados
escritor 1: termino da escrita no banco de dados v
escritor 2: escrevendo no banco de dados ^
escritor 1: criando dados
escritor 2: termino da escrita no banco de dados v
leitor 3: lendo banco de dados ^
leitor 4: lendo banco de dados ^
leitor 1: lendo banco de dados ^
leitor 2: lendo banco de dados ^
escritor 2: criando dados
leitor 1: termino da leitura banco de dados v
leitor 1: usando dados
leitor 2: termino da leitura banco de dados v
leitor 2: usando dados
leitor 3: termino da leitura banco de dados v
leitor 3: usando dados
leitor 4: termino da leitura banco de dados v
escritor 1: escrevendo no banco de dados ^
leitor 4: usando dados
escritor 1: termino da escrita no banco de dados v
escritor 2: escrevendo no banco de dados ^
escritor 1: criando dados

Podemos ver que varios threads podem estar lendo o banco de dados ao mesmo tempo, porem ao escrever somente um thread por vez pode fazer isso.

Questao 1 da prova: O Banheiro

Existe um banheiro, tanto mulheres quanto homems podem usar este banheiro, porem nunca podera ocorrer de termos mulheres e homems ao mesmo tempo usando o banheiro. A regra entao diz que se uma mulher entra no banheiro, mais mulheres podem entrar e homens não. Quando a ultima mulher sai, pode entrar um homem, e entao outros homems entrarao e mulher não.

Segue a implementacao:

/* 
 * File:   q1.c
 * Author: pedro
 *
 * Created on May 6, 2009, 8:40 PM
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
 
#define VAZIO 0
#define MULHER 1
#define HOMEM 2
 
int placa;
sem_t banheiro,mutexM,mutexH;
int num_mulheres=0,num_homens=0;
 
 void usa_o_banheiroM(int i)
 {
     printf("Mulher %d: usando banheiro \n",i);
     printf("M: %d H: %d\n",num_mulheres,num_homens);
     double time = drand48();
    time = (2.0f+3.0f*time)*1000000.0f;
    usleep((int)time);
 }
 void usa_o_banheiroH(int i)
 {
    printf("Homem %d: usando banheiro\n",i);
    printf("M: %d H: %d\n",num_mulheres,num_homens);
     double time = drand48();
    time = (2.0f+3.0f*time)*1000000.0f;
    usleep((int)time);
 }
 
void Mulher_quer_entrar(int i)
{
    printf("Mulher %d: quero usar o banheiro\n",i);
    printf("M: %d H: %d\n",num_mulheres,num_homens);
    sem_wait(&mutexM);
    if(placa != MULHER)sem_wait(&banheiro);
    ++num_mulheres;
    placa = MULHER;
    sem_post(&mutexM);
}
 
void Mulher_sai(int i)
{
    sem_wait(&mutexM);
    --num_mulheres;
    if(num_mulheres==0)
    {
        placa == VAZIO;
        sem_post(&banheiro);
    }
    sem_post(&mutexM);
    printf("Mulher %d: terminei\n",i);
    printf("M: %d H: %d\n",num_mulheres,num_homens);
}
 
void Homem_quer_entrar(int i)
{
    printf("Homem %d: quero usar o banheiro\n",i);
    printf("M: %d H: %d\n",num_mulheres,num_homens);
    sem_wait(&mutexH);
    if(placa != HOMEM)sem_wait(&banheiro);
    ++num_homens;
    placa = HOMEM;
    sem_post(&mutexH);
}
 
void Homem_sai(int i)
{
    sem_wait(&mutexH);
    --num_homens;
    if(num_homens==0)
    {
        placa = VAZIO;
        sem_post(&banheiro);
    }
    sem_post(&mutexH);
    printf("Homem %d: terminei\n",i);
    printf("M: %d H: %d\n",num_mulheres,num_homens);
}
 
void * mulher(void * id)
{
    int i = *(int *)id;
    Mulher_quer_entrar(i);
    usa_o_banheiroM( i);
    Mulher_sai( i);
    pthread_exit(NULL);
}
 
void * homem (void * id)
{
    int i = *(int *)id;
    Homem_quer_entrar(i);
    usa_o_banheiroH( i);
    Homem_sai( i);
    pthread_exit(NULL);
}
 
void * criador_homem(void * a)
{
    pthread_t *homemThread;
    int i = 0;
    while(1)
    {
        ++i;
        double time = drand48();
        time = (1.0f+5.0f*time)*1000000.0f;
        usleep((int)time);
        homemThread = (pthread_t*)malloc(sizeof(pthread_t));
        pthread_create(homemThread,NULL,homem,(void*)&i);
    }
}
void * criador_mulher(void * a)
{
     pthread_t *mulherThread;
     int i = 0;
    while(1)
    {
        ++i;
        double time = drand48();
        time = (1.0f+5.0f*time)*1000000.0f;
        usleep((int)time);
        mulherThread = (pthread_t*)malloc(sizeof(pthread_t));
        pthread_create(mulherThread,NULL,mulher,(void*)&i);
    }
}
 
int main(int argc, char** argv)
{
    srand48(time(NULL));
    pthread_t thread1,thread2;
    sem_init(&banheiro,0,1);
    sem_init(&mutexH,0,1);
    sem_init(&mutexM,0,1);
    placa=VAZIO;
    pthread_create(&thread1,NULL,criador_mulher,NULL);
    pthread_create(&thread2,NULL,criador_homem,NULL);
 
    pthread_join(thread1,NULL);
 
    return (EXIT_SUCCESS);
}

Executando:

Homem 2: quero usar o banheiro
M: 0 H: 0
Homem 2: usando banheiro
M: 0 H: 1
Mulher 2: quero usar o banheiro
M: 0 H: 1
Homem 2: terminei
M: 1 H: 0
Mulher 2: usando banheiro
M: 1 H: 0
Homem 3: quero usar o banheiro
M: 1 H: 0
Mulher 3: quero usar o banheiro
M: 1 H: 0
Mulher 3: usando banheiro
M: 2 H: 0
Homem 4: quero usar o banheiro
M: 2 H: 0
Mulher 2: terminei
M: 1 H: 0
Mulher 4: quero usar o banheiro
M: 1 H: 0
Mulher 4: usando banheiro
M: 2 H: 0
Mulher 3: terminei
M: 1 H: 0
Homem 5: quero usar o banheiro
M: 1 H: 0
Homem 3: usando banheiro
M: 0 H: 2
Homem 4: usando banheiro
M: 0 H: 2
Mulher 4: terminei
M: 0 H: 2
Homem 5: usando banheiro
M: 0 H: 3
Homem 6: quero usar o banheiro
M: 0 H: 3
Homem 6: usando banheiro
M: 0 H: 4
Mulher 5: quero usar o banheiro
M: 0 H: 4
Homem 5: terminei
M: 0 H: 3
Homem 3: terminei
M: 0 H: 2
Homem 4: terminei
M: 0 H: 1
Homem 6: terminei
M: 0 H: 0
Mulher 5: usando banheiro
M: 1 H: 0
Homem 7: quero usar o banheiro
M: 1 H: 0
Mulher 6: quero usar o banheiro
M: 1 H: 0
Mulher 6: usando banheiro
M: 2 H: 0
Mulher 5: terminei
M: 1 H: 0
Homem 8: quero usar o banheiro
M: 1 H: 0
Mulher 7: quero usar o banheiro
M: 1 H: 0
Mulher 7: usando banheiro
M: 2 H: 0
Mulher 6: terminei
M: 1 H: 0
Mulher 7: terminei
M: 0 H: 2
Homem 8: usando banheiro
M: 0 H: 2
Homem 7: usando banheiro
M: 0 H: 2
Homem 9: quero usar o banheiro
M: 0 H: 2
Homem 9: usando banheiro
M: 0 H: 3
Homem 8: terminei
M: 0 H: 2
Mulher 8: quero usar o banheiro
M: 0 H: 2
Homem 7: terminei
M: 0 H: 1

A saida acima mostra o numero de mulheres e homens no banheiro. Podemos ver que quando tem homem o numero de mulheres zera e vice versa.

Questao 7 da prova: Send e Receive

Implementacao das funcoes send e receive, para o envio e recebimento de mensagens entre 2 threads, onde a thread que recebe trava quando tenta receber e não há mensagens, e a thread que envia trava quando tenta enviar e o sistema esta lotado de mensagens não lidas. As mensagens enviadas ficam em uma fila, ou sejam as novas sao adicionadas no final e sempre sao lidas as primeiras da fila. Foram utilizadas 12 frases pre-definidas como as mensagens a ser enviadas de um thread a outro. Foi definido como 20 o maximo numero de mensagens no sistema.

Codigo:

/* 
 * File:   senrec.c
 * Author: pedro
 *
 * Created on May 8, 2009, 3:01 AM
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <time.h>
 
#define Init pthread_mutex_init
#define Lock pthread_mutex_lock
#define Unlock pthread_mutex_unlock
 
#define BUFFERSIZE 20
 
int buffer[BUFFERSIZE];
int pos=0,pos2=0;
sem_t usedspaces,emptyspaces;
pthread_mutex_t mutex;
 
char* messages[] = {"hello"," hi"," bye"," how are you"," let's go"," I'm fine",
" Thanks"," Let's play DOTA ","Do you wanna dance?"," I'll kick some alien asses",
" Your face ,your ass... What's the diference?","Groovy"};
 
void send(int msg)
{
    sem_wait(&emptyspaces);
    Lock(&mutex);
    buffer[pos%BUFFERSIZE]=msg;
    pos++;
    sem_post(&usedspaces);
    Unlock(&mutex);
}
 
int receive()
{
    int msg;
    sem_wait(&usedspaces);
    Lock(&mutex);
    msg = buffer[pos2%BUFFERSIZE];
    pos2++;
    sem_post(&emptyspaces);
    Unlock(&mutex);
    return msg;
}
 
void *sender(void * arg)
{
    while(1)
    {
        int msg = rand()%12;
        printf("sending msg: %s\n",messages[msg]);
        send(msg);
 
        double time = drand48();
        time = (2.0f+1.0f*time)*1000000.0f;
        usleep((int)time);
    }
}
 
void *receiver(void * arg)
{
    while(1)
    {
        double time = drand48();
        time = (4.0f+3.0f*time)*1000000.0f;
        usleep((int)time);
        int msg = receive();
 
        printf("Received msg: %s\n",messages[msg]);   
    }
}
 
int main(int argc, char** argv)
{
    srand(time(NULL));
    Init(&mutex,NULL);
    sem_init(&usedspaces,0,0);
    sem_init(&emptyspaces,0,20);
    pthread_t senderThread,receiverThread;
 
    pthread_create(&senderThread,NULL,sender,NULL);
    pthread_create(&receiverThread,NULL,receiver,NULL);
 
    pthread_join(senderThread,NULL);
    return (EXIT_SUCCESS);
}

Ao executar o programa, temos a seguinte saida:

sending msg: Thanks
sending msg: I'm fine
Received msg: Thanks
sending msg: let's go
sending msg: Groovy
sending msg: Thanks
Received msg: I'm fine
sending msg: hello
sending msg: I'm fine
Received msg: let's go
sending msg: hello
sending msg: I'll kick some alien asses
Received msg: Groovy
sending msg: Thanks
sending msg: bye
Received msg: Thanks
sending msg: hello
sending msg: hello
sending msg: how are you
Received msg: hello
sending msg: I'm fine
sending msg: hi
Received msg: I'm fine
sending msg: bye
sending msg: Let's play DOTA
Received msg: hello
sending msg: let's go
sending msg: hi
sending msg: Thanks
Received msg: I'll kick some alien asses

Nesse exemplo foi definido que o thread que envia esta mais rapido que o thread que recebe e portanto ocorre um acumulo de mensagens no sistema .

+Conclusões

A implmentação desses problemas de threads foi muito bom para uma maior compreenção de como os threads interagem entre si e de como é dificil encontrar erros em problemas envolvendo threads. Varias vezes surgiam erros sem explicação mas que depois eram descobertos como um deadlock causado por uso errado de semaforos ou mutexes entre outros erros.

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