sema faro
TRANSCRIPT
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
1. INTRODUÇÃO
Uma Thread (Linha ou Escalonamento de execução) é uma forma de um processo que
dividir a si mesmo em duas mais tarefas que podem ser executadas concorrentemente.
Possibilitando implementar aplicações concorrente com uma maior eficiência. Uma
thread permite, por exemplo, que o usuário de um programa utilize uma funcionalidade
do ambiente enquanto outras linhas de execução realizam outros cálculos e operações.
Com isso temos possibilidade de implementa um processo de várias formas, uma delas e
a possibilidade de interlaçar dois ou mais programas, sendo que ao executar certos trechos
críticos, pode-se ter alguns comportamentos instável sendo que seus resultados dependem
integralmente de uma ordem de execução, que na visão de um programados isso não pode
ocorrer. Para sarnarmos isso deve-se usar uma técnica em programação concorrente para
evitar que dois processos ou Threads tenham acesso simultaneamente a um recurso
compartilhado (acesso esse denominado secção crítica) que é a Exclusão Mútua.
Muitos métodos forma usados para garantir a exclusão mútua, mas em 1968 Dijkstra criou
o conceito de Semáforos, e também sendo capazes de resolver uma grande variedades de
problemas.
O Semáforo é um objeto com apenas um membro de dados representados por um inteiro
sem sinal e dois métodos que definem às únicas operações permitidas: WAIT(S), se é um
positivo, decrementa o valor de S. se S e igual a zero, suspende a thread no semáforo.
SIGNAL(S), acorda uma Thread que esteja suspensa no semáforo. Caso não haja
nenhuma, incrementa o valor de S. Com isso é possível satisfazer as quatro propriedades
básicas para a implementação de programação concorrente utilizando threads: Exclusão
mútua, ausência de deadlock, ausência de inanição e chegada na ausência de contenção.
2. OBJETIVOS
• Montar o Algoritmo do problema e em seguida implementá-lo. Deve-se imprimir
mensagens mostrando o que está acontecendo no programa implementado
3. FERRAMENTAS UTILIZADAS
Computador com o Software Dev-C++.
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
4. DESENVOLVIMENTO
Conforme solicitado, foram implementados os seguintes problemas:
1. Produtor e Consumidor,
2. Filósofos,
3. Salão de Barbeiro,
4. Fumantes,
5. Jantar dos Selvagens,
6. Montanha Russa,
7. Filme e
8. Pombo Correio.
Todos os programas a seguir foram implantados e suas execuções testadas, e seu
funcionamento foi todo comentado no próprio código e redigido no corpo deste trabalho.
4.1 Produtor e Consumidor
Neste programa foi implementado conforme implementação abaixo com seus
comentários inseridos. Sendo que para alteração do Buffer para poder de ir de 10 a 24
posições de armazenamento, basta alterar o valor de N. Analisando a o algoritmo pode se
provar as propriedades, sendo que o produtor não pode inserir dados em um buffer cheio,
o consumidor não pode consumir dados no buffer, ausência de deadlock e não ocorre
inanição de nenhum processo.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#include <string.h>
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
#define N 5
#define prod 5 //DEFINE O NUMERO DE PRODUTORES
#define cons 5 //DEFINE OS NUMEROS DE CONSUMIDORES
//DEFINE VALORES PARA FACILITAR
#define Produzir 0
#define Consumir 1
//DECARAÇÃO DOS SEMAFAROS
HANDLE VAZIOS;
HANDLE CHEIOS;
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
// DECLARAÇÃO DAS FUNÇÕES
DWORD WINAPI Produtor(LPVOID);
DWORD WINAPI Consumidor(LPVOID);
int Buffer[N]; // Buffer circular
int InIndex = 0; // Índice para posição livre para inserção de dados
int OutIndex = 0; // Índice para posição ocupada contendo dado
int cont=0;
int main(){
int i;
//DECLARA AS THREADS
HANDLE PThreads[prod];
HANDLE CThreads[cons];
DWORD dwThreadIdcons, dwTheadIdprod;
DWORD dwExitCodecons = 0, dwExitCodeprod = 0;
DWORD dwRetcons, dwRetprod;
//CRIA SEMAFAROS
VAZIOS = CreateSemaphore(NULL,N,N,"VAZIO");
CHEIOS = CreateSemaphore(NULL,0,N,"CHEIO");
//CRIA THREADS PRODUTORES
for (i=0; i<prod; ++i) {
PThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)Produtor, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwTheadIdprod // cating necessário
);
if (PThreads[i]) printf("Produtor %d criada Id= %0x \n", i, dwTheadIdprod);
}
//CRIA THREADS CONSUMIDOR
for (i=0;i<cons; ++i){
CThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION) Consumidor, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIdcons // cating necessário
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
);
if (CThreads[i]) printf("Consumidor %d criada Id= %0x \n", i, dwThreadIdcons);
}
dwRetprod = WaitForMultipleObjects(prod, PThreads,TRUE,INFINITE);
CheckForError((dwRetprod >= WAIT_OBJECT_0) && (dwRetprod < WAIT_OBJECT_0 +
prod));
dwRetcons = WaitForMultipleObjects(cons, CThreads,TRUE,INFINITE);
CheckForError((dwRetcons >= WAIT_OBJECT_0) && (dwRetcons < WAIT_OBJECT_0 +
cons));
//APAGA REFERENCIA DE THREADS
for (i=0; i<prod; ++i){
GetExitCodeThread(PThreads[i], &dwExitCodeprod);
CloseHandle(PThreads[i]); // apaga referência ao objeto
} // for
for (i=0; i<cons; ++i){
GetExitCodeThread(CThreads[i], &dwExitCodecons);
CloseHandle(CThreads[i]); // apaga referência ao objeto
} // for
//APAGA REFERENCIA DOS SEMAFAROS
CloseHandle(CHEIOS);
CloseHandle(VAZIOS);
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
return EXIT_SUCCESS;
} // main
DWORD WINAPI Produtor(LPVOID i){
LONG lOldValue;
Sleep(1000); // da um tempo para criar todo mundo e aumentar a concorrência
do{
Sleep(1000);
//ESPERA QUE HAJA ESPAÇO LIVRE
WaitForSingleObject(VAZIOS, INFINITE);
Sleep(100);
//INSERE DADO NO BUFFER
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
Buffer[InIndex] = Produzir;
cont++;
printf("O Produtor %d Produziu!\n", cont);
// Aponta próxima posição livre
InIndex = (InIndex + 1)%N;
//SINALIZA CHEIO
ReleaseSemaphore(CHEIOS, 1, &lOldValue);
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
DWORD WINAPI Consumidor(LPVOID i){
LONG lOldValue;
Sleep(1000); // da um tempo para criar todo mundo e aumentar a concorrência
do{
Sleep(1000);
//ESPERA QUE HAJA DADO PARA SER CONSUMIDO
WaitForSingleObject(CHEIOS, INFINITE);
Sleep(1000);
// Insere dado no buffer
Buffer[OutIndex] = Consumir;
printf("O Consumidor %d Consumiu!\n", cont);
cont--;
//APONTA PARA PROXIMA POSIÇÃO OCUPADA
OutIndex = (OutIndex + 1)%N;
//SINALIZA VAZIO
ReleaseSemaphore(VAZIOS, 1, &lOldValue);
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc.
4.2.Filósofos
Um dos problema clássicos mais famosos da história da computação. Cinco filósofos
estão sentados em torno de uma mesa circular, que tem em seu centro um prato
inesgotável de sushis (na história original era spaghetti, mas você precisa de um único
talher para comer spaghetti ou de dois talheres diferentes: um garfo e uma colher). Sobre
a mesa, entre cada dois filósofos está um talher japonês (hashi). Cada filósofo para comer
deve pegar dois talheres, uma vez que é difícil equilibrar um sushi em um único talher.
Cada filósofo realiza um loop infinito em que pensa, toma os talheres um a um, come e
devolve os talheres à mesa. As regrasa serem obedecidas são:
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
P1: Dois filósofos não podem segurar um mesmo talher simultaneamente.
P2: O filósofo só come, quando tem dois talheres
P3: Não deve haver deadlock, situação em que nenhum dos filósofos consegue comer.
P4: Não pode haver inanição (neste caso inanição propriamente dita), isto é, um filósofo
querendo comer, deve eventualmente ter acesso aos dois talheres.
Eventualmente aqui significa: o evento (comer) ocorre com certeza, em algum instante
no futuro.
Conforme o enunciado foi implementado o algoritmo que se segue, com os comentários do
programa.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
#define N 5 //DEFINE A QUANTIDADE DE FILOSOFO
#define ESQUERDA (j + N -1)%N //DEFINE A ESQUERDA DE UM FILOSOFO
#define DIREITA (j+1)%N //DEFINE A DIREITA DO FILOSOFO
//ENUMERAÇÃO DOS ESTADOS
#define PENSANDO 0
#define COM_FOME 1
#define COMENDO 2
int Estado[N]; //BUFFER DOS ESTADOS
//DECLAÇÃO DOS SEMAFAROS
HANDLE MUTEX;
HANDLE S[N];
//FUNÇÕES DE TESTES E MOSTRA
void Pega_talheres(int);
void Devolve_talheres(int);
void Test(int);
void Mostrar(void);
DWORD WINAPI Filosofo(int); // declaração da função
int main()
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
{
HANDLE hThreads[N]; //DECLARAÇÃO DA THREAD
int p;
DWORD dwThreadId;
DWORD dwExitCode = 0;
DWORD dwRet;
char filosofo;
//CRIAÇÃO DO MUTEX
MUTEX = CreateMutex(NULL, FALSE, "filosofo");
CheckForError(MUTEX);
//CRIAÇÃO SEMAFARO
for (p=0; p<N; ++p){
S[p] = CreateSemaphore(NULL,N,1,"filosofos");
}
//CRIAÇÃO DAS THREADS
for (p=0; p<N; ++p){
hThreads[p] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)Filosofo, // casting necessário
(LPVOID)p,
0,
(CAST_LPDWORD)&dwThreadId // casting necessário
);
if (hThreads[p]) printf("Filosofo %d Id= %0x \n", p, dwThreadId);
} // for
// Espera todas as threads terminarem
dwRet = WaitForMultipleObjects(N,hThreads,TRUE,INFINITE);
CheckForError((dwRet >= WAIT_OBJECT_0) && (dwRet < WAIT_OBJECT_0 + N));
for (p=0; p<N; ++p) {
dwRet=GetExitCodeThread(hThreads[p], &dwExitCode);
CheckForError(dwRet);
CloseHandle(hThreads[p]); // apaga referência ao objeto
} // for
//APAGA O MUTEX
CloseHandle(MUTEX);
//APAGA OS SEMAFAROS
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
for (p=0; p<N; ++p){
CloseHandle(S[p]);
}
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
return EXIT_SUCCESS;
} // main
DWORD WINAPI Filosofo(int j){
do{
Sleep(5000); // da um tempo para criar todo mundo e aumentar a concorrência
Pega_talheres(j); // Pega ambos os talheres
Devolve_talheres(j);// Devolve talheres
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
void Pega_talheres(int j){
WaitForSingleObject(MUTEX, INFINITE);// Anuncia que quer comer
Estado[j] = COM_FOME;
Mostrar();
Test(j); //Pede Talheres
ReleaseMutex(MUTEX);
WaitForSingleObject(S[j], INFINITE); // Fica a espera de talheres livres
}
void Devolve_talheres(int j){
WaitForSingleObject(MUTEX, INFINITE);
Estado[j] = PENSANDO; //Define um novo Estado
Mostrar();
Test(ESQUERDA); // Verifica se mudou estado do filósofo à esquerda
Test(DIREITA); // Verifica se mudou estado do filósofo à direita
ReleaseMutex(MUTEX);
}
void Test(int j) {
LONG lOldValue;
if ((Estado[j] == COM_FOME) && (Estado[ESQUERDA] != COMENDO) &&
(Estado[DIREITA]!=COMENDO))
{
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
Estado[j]=COMENDO;
Mostrar();
ReleaseSemaphore(S[j], 1, &lOldValue); // Se o filósofo tem os dois talheres disponíveis,
acorde-o
}
}
void Mostrar(){
int i;
for(i=1; i<=N; i++){
if(Estado[i-1] == PENSANDO){
printf("O filosofo %d esta pensando!\n", i);
}
if(Estado[i-1] == COM_FOME){
printf("O filosofo %d esta com fome!\n", i);
}
if(Estado[i-1] == COMENDO){
printf("O filosofo %d esta comendo!\n", i);
}
}
printf("\n");
}
4.3.Salão de Barbeiro
Um salão de barbeiro tem uma cadeira de barbear, 5 cadeiras de espera, e um barbeiro.
Quando não há clientes, o barbeiro se senta na cadeira de barbear e dorme. Um cliente
chegando nesta situação é prontamente atendido. Se o cliente chega e o barbeiro está
ocupado, o cliente verifica o número de cadeiras de espera livres. Se existir alguma livre,
o cliente se senta e espera, caso contrário, vai embora. Gerencie o salão de barbeiro
usando semáforos.
Segue o algoritmo
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
#define NCADEIRAS 5 //DEFINE A QUANTIDADE DE CADEIRAS DE ESPERA
#define NCLIENTES 10 //DEFINE A QUANTIDADE DE CLIENTES QUE ENTRAM NO SALÃO
#define NBARBEIRO 1 // DEFINE O NUMERO DE BARBEIRO
HANDLE SBARBEIROS; //SEMAFARO DE BARBEIROS
HANDLE SCLIENTES; //SEMAFARO CONTROLA ENTRADA DOS CLIENTES NA CADEIRA DE
ESPERA
HANDLE SMUTEX; //SEMAFARO PARA SENTA NA CADEIRA DO BARBEIRO
HANDLE LMUTEX; //SEMAFARO PARA LEVANTAR DA CADEIRA DO BARBEIRO
int ESTADO=0, SENTADO=0, j=0;
DWORD WINAPI cliente(LPVOID); // DECLARAÇÃO DA FUNÇÃO CLIENTE
DWORD WINAPI barbeiro(LPVOID); // DECLARAÇÃO DA FUNÇÃO BARBEIRO
int main()
{
HANDLE BThreads[NBARBEIRO]; //THEADS BARBEIRO
HANDLE CThreads[NCLIENTES]; //THEADS CLIENTES
int i;
DWORD dwThreadIdcons, dwTheadIdprod;
DWORD dwExitCodecons = 0, dwExitCodeprod = 0;
DWORD dwRetcons, dwRetprod;
//CRIAÇÃO DOS SEMAFAROS
SMUTEX = CreateSemaphore(NULL,1,1,"MUTEX");
LMUTEX = CreateSemaphore(NULL,0,1,"MUTEX");
SCLIENTES = CreateSemaphore(NULL,1,1,"CLIENTES");
SBARBEIROS = CreateSemaphore(NULL,0,1,"BARBEIRO");
//CRIAÇÃO DA THREADS DO BARBEIRO
for (i=0; i<NBARBEIRO; ++i) {
BThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)barbeiro, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwTheadIdprod // cating necessário
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
);
if (BThreads[i]) printf("Barbeiro %d criada Id= %0x \n", i, dwTheadIdprod);
}//FOR
//CRIAÇÃO DAS THREADS DOS CLIENTES
for (i=0;i<NCLIENTES; ++i){
CThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)cliente, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIdcons // cating necessário
);
if (CThreads[i]) printf("Cliente %d criada Id= %0x \n", i, dwThreadIdcons);
}//FOR
//CHECA ERRO
dwRetprod = WaitForMultipleObjects(NBARBEIRO, BThreads,TRUE,INFINITE);
CheckForError((dwRetprod >= WAIT_OBJECT_0) && (dwRetprod < WAIT_OBJECT_0 +
NCLIENTES));
dwRetcons = WaitForMultipleObjects(NCLIENTES, CThreads,TRUE,INFINITE);
CheckForError((dwRetcons >= WAIT_OBJECT_0) && (dwRetcons < WAIT_OBJECT_0 +
NCLIENTES));
//APARGA A REFERENCIA DAS THEADS
for (i=0; i<NBARBEIRO; ++i){
GetExitCodeThread(BThreads[i], &dwExitCodeprod);
CloseHandle(BThreads[i]); // apaga referência ao objeto
} // for
for (i=0; i<NCLIENTES; ++i){
GetExitCodeThread(CThreads[i], &dwExitCodecons);
CloseHandle(CThreads[i]); // apaga referência ao objeto
} // for
//APAGA A REFERENCIA DOS SEMAFAROS
CloseHandle(SCLIENTES );
CloseHandle(SBARBEIROS);
CloseHandle(SMUTEX);
CloseHandle(LMUTEX);
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
return EXIT_SUCCESS;
} // main
DWORD WINAPI barbeiro(LPVOID i)
{
LONG lOldValue;
Sleep(1000);
do{
//CONTROLA O BARBEIRO
WaitForSingleObject(SBARBEIROS, INFINITE);
ESTADO = ESTADO -1;
Sleep(1000);//TEMPO DE CORTE DO CABELO
printf("Barbeiro TERMINO cabelo de um cliente!\n");
//ACIONA O CLIENTE A LEVANTAR DA CADEIRA DO BARBEIRO
ReleaseSemaphore(LMUTEX, 1, &lOldValue);
//ACIONA O CLIENTE A SENTA NA CADEIRA DO BARBEIRO
ReleaseSemaphore(SMUTEX, 1, &lOldValue);
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
DWORD WINAPI cliente(LPVOID i)
{
LONG lOldValue;
do{
//CONTROLA ENTRADA DE CLIENTES
WaitForSingleObject(SCLIENTES, INFINITE);
Sleep(2000); //CONTROLA TEMPO DE ENTRADA DE CADA CLIENTE
printf("Cliente ENTRA!\n");
//SE TIVER CADEIRA SENTA
if (ESTADO < NCADEIRAS){
// SE NAO TEM CLIENTE DORME
if (ESTADO==0)
printf("BARBEIRO DORMINDO\n ");
else
printf("Cliente %d Senta na cadeira de Espera!\n",i);
ESTADO = ESTADO +1;
//ACORDA UM CLIENTE PARA ENTRAR NA BARBERIA
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
ReleaseSemaphore(SCLIENTES, 1, &lOldValue);
//CONTROLA A CADEIRA DO BARBEIRO (SENTA)
WaitForSingleObject(SMUTEX, INFINITE);
//ACORDA O BARBEIRO
ReleaseSemaphore(SBARBEIROS, 1, &lOldValue);
printf("Cliente %d Senta na Cadeira do Barbeiro\n", i);
//CONTROLA A CADEIRA DO BABEIRO (LEVANTA)
WaitForSingleObject(LMUTEX, INFINITE);
}//for
//SE NAO TIVER CADEIRAS VAI EMBORA
else{
//ACORDA UM CLIENTE PARA ENTRAR NA BARBERIA
ReleaseSemaphore(SCLIENTES, 1, &lOldValue);
printf("Cliente %d saiu da barbearia porque estava lotada!\n", i);
}//else
}while(TRUE);
_endthreadex(0);
return(0);
}//BoxFunc
4.4. Fumantes
Um sistema possui 3 processos fumantes inveterados. Cada fumante prepara cigarros e
os fuma em um loop infinito. Para fumar um cigarro, três ingredientes são necessários:
papel, tabaco e fósforos. Um dos processos fumantes tem tabaco, o outro papel e o outro
fósforos. O agente tem um suprimento infinito dos três ingredientes. O agente coloca dois
dos ingredientes escolhidos aleatoriamente sobre a mesa. O fumante que possui o terceiro
ingrediente pode então fumar o seu cigarro. Após fumar, este processo sinaliza o agente
que então escolhe dois novos ingredientes e o processo continua. Resolva o problema
usando semáforos. O processo fumante solicita os recursos de que necessita e é atendido
quando o recurso estiver disponível.
Observe que não existe memória global compartilhada!
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
//DEFINE O NUMERO DE FUMANTES
#define N 3
#define A 1
//ENUMERA OS INGREDIENTES
#define PAPEL 0
#define TABACO 1
#define FOSFORO 2
int ale = 0; //NUMERO ALEATORIO DO AGENTE
//HANDLE DOS SEMAFAROS
DWORD WINAPI AGENTE(int);
DWORD WINAPI FUMANTES(int);
HANDLE MUTEX;
HANDLE SPAPEL;
HANDLE STABACO;
HANDLE SFOSFORO;
int main()
{
//HANDLE DAS THREADS
HANDLE FThreads[N];
HANDLE AThreads[1];
DWORD dwThreadIdcons;
DWORD dwExitCodecons = 0;
DWORD dwRetcons;
DWORD dwThreadIda;
DWORD dwExitCodea = 0;
DWORD dwReta;
int i;
MUTEX = CreateSemaphore(NULL,1,1,"MUTEX");
SPAPEL = CreateSemaphore(NULL,0,1,"PAPEL");
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
STABACO = CreateSemaphore(NULL,0,1,"TABACO");
SFOSFORO = CreateSemaphore(NULL,0,1,"FOSFORO");
//CRIA AS TRHEADS DOS FUMANTES
for (i=0;i<N; ++i){
FThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)FUMANTES, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIdcons // cating necessário
);
if (FThreads[i]) printf("FUMANTES %d criada Id= %0x \n", i, dwThreadIdcons);
}//FOR
//CRIA A THREDAS DO AGENTE
for (i=0;i<A; ++i){
AThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)AGENTE, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIda // cating necessário
);
if (AThreads) printf("AGENTE criada Id= %0x \n", dwThreadIda);
}//FOR
dwRetcons = WaitForMultipleObjects(N, FThreads,TRUE,INFINITE);
CheckForError((dwRetcons >= WAIT_OBJECT_0) && (dwRetcons < WAIT_OBJECT_0 + N));
dwReta = WaitForMultipleObjects(A, AThreads,TRUE,INFINITE);
CheckForError((dwReta >= WAIT_OBJECT_0) && (dwReta < WAIT_OBJECT_0 + A));
for (i=0; i<N; ++i){
GetExitCodeThread(FThreads[i], &dwExitCodecons);
CloseHandle(FThreads[i]); // apaga referência ao objeto
}// for
for (i=0; i<A; ++i){
GetExitCodeThread(AThreads, &dwExitCodea);
CloseHandle(AThreads);//apaga referencia ao objeto threads
}// for
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
//apaga referneica ao objeto semafaro
CloseHandle(MUTEX);
CloseHandle(SPAPEL);
CloseHandle(STABACO);
CloseHandle(SFOSFORO);
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
return EXIT_SUCCESS;
} // main
DWORD WINAPI FUMANTES(int i){
int p;
LONG lOldValue;
Sleep(1000);
do{
//ANUNCIA QUE FUMANTE - PAPEL QUER FUMAR
if (i==PAPEL){
WaitForSingleObject(SPAPEL, INFINITE);
printf("FUMANDO - PEPEL \n");
}
//ANUNCIA QUE FUMANTE - TABACO QUER FUMAR
if (i==TABACO){
WaitForSingleObject(STABACO, INFINITE);
printf("FUMANDO - TABACO \n");
}
//ANUNCIA QUE FUMANTE - FOSFORO QUER FUMAR
if (i==FOSFORO){
WaitForSingleObject(SFOSFORO, INFINITE);
printf("FUMANDO - FOSFORO \n");
}
Sleep(1000);//PARA PARA FUMAR
printf("Para de Fumar Aciona o Agente\n\n");
//ACORDA O AGENTE
ReleaseSemaphore(MUTEX,1,&lOldValue);
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
DWORD WINAPI AGENTE(int i){
Sleep(1000);
LONG lOldValue;
int p;
do{
//ANUNCIA QUE O AGENTE QUE ADICIONAR INGREDIENTE
WaitForSingleObject(MUTEX, INFINITE);
ale = rand()%N ;
//AGENTE COLOCA INGREDIENTE ACORDA FUMANTE FOSFORO
if (ale == TABACO){
printf("Agente coloca PAPEL e FOSFORO \n");
//ACORDA O FUMANTE TABACO
ReleaseSemaphore(STABACO, 1, &lOldValue);
}
//AGENTE COLOCA INGREDIENTE ACORDA FUMANTE PAPEL
if (ale == FOSFORO){
printf("Agente coloca TABACO e PAPEL \n");
//ACORDA O FUMANTE FORSFORO
ReleaseSemaphore(SFOSFORO, 1, &lOldValue);
}
//AGENTE COLOCA INGREDIENTE ACORDA FUMANTE TABACO
if (ale == PAPEL){
printf("Agente coloca FOSFORO e TABACO \n");
//ACORDA O FUMANTE PAPEL
ReleaseSemaphore(SPAPEL, 1, &lOldValue);
}
}while(TRUE);
_endthreadex(0);
return(0);
}
4.5.Jantar dos Selvagens
Uma tribo de selvagens janta em conjunto, retirando missionários assados (para diminuir
o colesterol) de um grande pote que comporta até M missionários. Quando um selvagem
deseja comer ele se serve do pote, a menos que o pote esteja vazio. Se o pote está vazio,
o selvagem acorda um cozinheiro e espera até que este tenha assado mais missionários e
enchido o pote. Nos programas abaixo, substitua os marcadores em itálico por instruções
em pseudo linguagem de modo a garantir a perfeita sincronização entre cozinheiro e
selvagens.
#define N 10 //DEFINE OS SELVAGENS
#define M 5 //DEFINE OS missionários
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
//DECLARA OS SEMAFAROS
HANDLE cozinha;
HANDLE comida;
HANDLE mutex;
HANDLE enchendo;
//DECLARA AS THREADS
HANDLE Cozinheiro;
HANDLE Canibal[N];
//DECLARA AS FUNÇÕES
DWORD WINAPI Canibais(LPVOID);
DWORD WINAPI Cozinha(int);
int i=0;
int count = 0;
int main(){
DWORD dwThreadId;
DWORD dwExitCode = 0;
DWORD dwRet;
int i;
//CIRA OS SEMAFAROS
comida = CreateSemaphore(NULL, N, N , "Comida");
cozinha = CreateSemaphore(NULL, 0, 1 , "Cozinha");
mutex = CreateSemaphore(NULL, 1, 1 , "Mutex");
enchendo = CreateSemaphore(NULL,0,1,"Enchendo");
//CRIA AS THREADS CANIBAIS
for(i=0; i < N; i++){
Canibal[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)Canibais,
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadId );
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
if (Canibal[i]) printf("Thread %d criada com Id= %0x \n", 0,
dwThreadId);
}
//CRIA AS THREADS COZINHEIRO
Cozinheiro = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)Cozinha,
(LPVOID)0,
0,
(CAST_LPDWORD)&dwThreadId );
if (Cozinheiro) printf("Thread %d criada com Id= %0x \n", 0, dwThreadId);
for (i=0; i<N; ++i) {
dwRet = WaitForSingleObject(Canibal[i], INFINITE);
CheckForError(dwRet == WAIT_OBJECT_0);
GetExitCodeThread(Canibal[i], &dwExitCode);
printf("thread %d terminou com codigo de saida %d\n", i, dwExitCode);
CloseHandle(Canibal[i]); // apaga referência ao objeto
}
Sleep(10000);
CloseHandle(Canibal[0]);
printf("\nAcione uma tecla para terminar\n");
/*FIM DAS THREADS*/
/*FECHAMENTO DO HANDLE DOS SEMAFOROS*/
CloseHandle(comida);
CloseHandle(cozinha);
CloseHandle(mutex);
CloseHandle(enchendo);
/*FIM DO FECHAMENTO DO HANDLE DOS SEMAFOROS*/
getch(); }
DWORD WINAPI Cozinha(int index) {
LPLONG sc,sb,sm;
while(TRUE){
//ENTRADA DOS SELVAGENS PARA COMER
WaitForSingleObject(comida,INFINITE);
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
//CONTROLA A IDA NO POTE
WaitForSingleObject(mutex, INFINITE);
Sleep(1000);
//SE MISSIONARIOS MAIOR O IGUAL A M CHAMA COZINHEIRO
count++;
printf("Selvagem %d foi ao pote\n", i);
i = (i+1)%N;
Sleep(1000);
if (count >= M){
printf("Pote VAZIO\n");
printf("Selvagem %d chama cozinheiro\n", i);
//SOLICITA O COZINHEIRO
ReleaseSemaphore(cozinha,1,sb);
WaitForSingleObject(enchendo,INFINITE);
count = 0;
}
printf("Selvagem Comeu\n");
printf("Selvagem Descansa\n");
//ACORDA O SELVAGEM PARA IR AO POTE
ReleaseSemaphore(mutex,1,sb);
}
_endthreadex(0);
return(0);
}
DWORD WINAPI Canibais(LPVOID index) {
LPLONG sc,sb,sm;
while(TRUE){
//CHAMA O COZINHEIRO
WaitForSingleObject(cozinha,INFINITE);
printf("Cozinhario Enche POTE\n");
Sleep(2000);
//ENCHE O POTE
for (i=0;i<M;i++){
ReleaseSemaphore(comida,1,sb);
}
ReleaseSemaphore(enchendo,1,sb);
}
} //
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
4.6.Montanha Russa
Suponha que existam N processos do tipo passageiro e um processo do tipo carro de
montanha russa. Os passageiros esperam repetitivamente para dar uma volta no carro que
comporta C passageiro, C < N. Entretanto o carro só começa o seu trajeto se todos os
lugares estão ocupados. Use semáforos para criar os protocolos de entrada e saída da
seção crítica dos processos passageiro e carro. Conforme temos o algoritmo demostrado.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
//LEMBRANDO C<N
#define N 15 //DEFINE NUMEROS DE PASSAGEIROS
#define C 5*A //DEFINE NUMEROS DE CADEIRAS
#define A 2 //DEFINE A QUANTIDADE DE CARROS
int count = 0;
int espera=0;
//DEFINE SEMAFAROS
HANDLE EMUTEX;
HANDLE SMUTEX;
HANDLE CARRO;
//DEFINE FUNÇÕES
DWORD WINAPI PASSAGEIRO(LPVOID);
DWORD WINAPI CARROS(LPVOID); // declaração da função
int main()
{
int p;
DWORD dwThreadIdcons, dwTheadIdprod;
DWORD dwExitCodecons = 0, dwExitCodeprod = 0;
DWORD dwRetcons, dwRetprod;
int i;
//DEFINE TRHEADS
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
HANDLE PThreads[N];
HANDLE CThreads[A];
//CRIA SEMARAFOS
EMUTEX = CreateSemaphore(NULL,1,1,"MUTEX");
CARRO= CreateSemaphore(NULL,0,A,"CARRO");
SMUTEX = CreateSemaphore(NULL,0,1,"PASSAGEIROS");
//CRIA THREADS
for (i=0; i<N; ++i) {
PThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)PASSAGEIRO, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwTheadIdprod // cating necessário
);
if (PThreads[i]) printf("Passageiros %d criada Id= %0x \n", i, dwTheadIdprod);
}
//CRIA THREADS CARRO
for (i=0;i<A; ++i){
CThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION) CARROS, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIdcons // cating necessário
);
if (CThreads[i]) printf("Carro %d criada Id= %0x \n", i, dwThreadIdcons);
}
//CHECA THREADS
dwRetprod = WaitForMultipleObjects(N, PThreads,TRUE,INFINITE);
CheckForError((dwRetprod >= WAIT_OBJECT_0) && (dwRetprod < WAIT_OBJECT_0 + N));
dwRetcons = WaitForMultipleObjects(A, CThreads,TRUE,INFINITE);
CheckForError((dwRetcons >= WAIT_OBJECT_0) && (dwRetcons < WAIT_OBJECT_0 +
A));
//APAGA REFERENCIA DAS THREADS
for (i=0; i<N; ++i){
GetExitCodeThread(PThreads[i], &dwExitCodeprod);
CloseHandle(PThreads[i]); // apaga referência ao objeto
} // for
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
//APAGA REFERENCIA DA THREADS
for (i=0; i<A; ++i){
GetExitCodeThread(CThreads[i], &dwExitCodecons);
CloseHandle(CThreads[i]); // apaga referência ao objeto
} // for
//APAGA REFERENCIA DOS SEMAFAROS
CloseHandle(EMUTEX);
CloseHandle(CARRO);
CloseHandle(SMUTEX);
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
return EXIT_SUCCESS;
} // main
DWORD WINAPI PASSAGEIRO(LPVOID j)
{
LONG lOldValue;
Sleep(1000); // da um tempo para criar todo mundo e aumentar a concorrência
do{
//CONTROLA A ESPERA DE PASSAGEIROS EM FILA
WaitForSingleObject(EMUTEX, INFINITE);
Sleep(1000);//CONTROLE DE ENTRADA DE CADA PASSAGIRO
count++; //CONTA A QUANTIDADE DE PASSAGEIROS
//SE MENOR QUE A CAPACIDADE ENTRA PASSAGEIRO
if (count<C){
//ATIVA A ENTRADA DO PASSAGEIRO
ReleaseSemaphore(EMUTEX, 1, &lOldValue);
printf("%d Passageiros ENTROU\n", j);
//ESPERA DE CARRO CHEGAR
WaitForSingleObject(SMUTEX, INFINITE);
}
//SE IGUAL A CAPACIDADE ENTRA PASSAGEIRO E ACIONA O CARRO
if (count==C){
ReleaseSemaphore(EMUTEX, 1, &lOldValue);
printf("%d Passageiros ENTROU\n", j);
ReleaseSemaphore(CARRO, A, &lOldValue);
//ESPERA DE CARRO CHEGAR
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
WaitForSingleObject(SMUTEX, INFINITE);
}
//SE MENOR QUE A CAPACIDADE PASSAGEIRO AGUARDA
if (count>C){
ReleaseSemaphore(EMUTEX, 1, &lOldValue);
printf("%d Passageiros AGUARDAM o Carro\n", j);
}
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
DWORD WINAPI CARROS(LPVOID j){
LONG lOldValue;
int i;
Sleep(1000);// da um tempo para criar todo mundo e aumentar a concorrência
do{
printf("Carro Espera Passageiros\n");
//ACORDA O CARRO QUANDO ACIONADO
WaitForSingleObject(CARRO,INFINITE);
printf("Carro CHEIO ---- SAIU ----\n");
Sleep(1000);//ESPERA CARRO DA VOLTA
printf("Carro Chego Passageiros Saindo\n");
Sleep(1000);//ESPERA SAIDA DOS PASSAGERIOS
//AVISA QUE CHEGO
for (i=0;i<C; ++i){
ReleaseSemaphore(SMUTEX, 1, &lOldValue);
}
printf("TODOS OS PASSAGEIROS SAIRAM\n");
count=0;//APOS PASSAGEIROS SAIREM ZERA O CONTADOR
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
4.7.Filme
Em uma determinado Stand uma feira, um demonstrador apresenta um filme sobre a vida
de Hoare, quando 10 pessoas chegam, o demonstrador fecha o pequeno auditório que não
comporta mais do que essa plateia. Novos candidatos a assistirem o filme devem espera
a próxima exibição. Esse filme faz muito sucesso com um grupo grande de Fãs (de bem
mais de 10 pessoas), que permanecem na feira só assistindo o filme seguidas vezes. Cada
vez que um desses fãs consegue assistir uma vez o filme por completo, ele vai telefonar
para casa para contar alguns detalhes novos para a sua mãe. Depois de telefonar ele volta
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
mais uma vez ao stand para assistir ao filme outra vez. Usando semáforos, modelo o
processo fã e o processo demonstrador. Lembrando que existem muitos fãs e apenas um
demonstrador. Como cada fã é muito ardoroso, uma vez que ele chega ao stand são sai
dali até assistir ao filme. Suponha que haja muitos telefones disponíveis na feira e,
portanto que a tarefa de telefonar para casa não impõe nenhuma necessidade de
sincronização. Segue o algoritmo.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
#define STAND 10 //DEFINE A CAPACIDADE
#define NFAS 11 //DEFINE A QUANTIDADE DE FAS
#define NDEMONSTRADOR 1 // DEFINE O NUMERO DE DEMONSTRADOR
HANDLE SFAS; //SEMAFARO DE FAS
HANDLE EMUTEX; //SEMAFARO CONTROLA ENTRADA DOS FAS
HANDLE SMUTEX; //SEMAFARO CONTROLA SAIDA DOS FAS
HANDLE SDEMONSTRADOR;
int cont=0;
DWORD WINAPI FA(LPVOID); // DECLARAÇÃO DA FUNÇÃO FA
DWORD WINAPI DEMONSTRADOR(LPVOID); // DECLARAÇÃO DA FUNÇÃO DEMOSTRADRO
int main()
{
HANDLE BThreads[NFAS]; //THEADS FÃS
HANDLE CThreads[NDEMONSTRADOR]; //THEADS DEMONSTRDOR
int i;
DWORD dwThreadIdcons, dwTheadIdprod;
DWORD dwExitCodecons = 0, dwExitCodeprod = 0;
DWORD dwRetcons, dwRetprod;
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
//CRIAÇÃO DOS SEMAFAROS
SDEMONSTRADOR = CreateSemaphore(NULL,0,1,"SDEMONSTRADOR");
EMUTEX = CreateSemaphore(NULL,1,1,"ENTRA");
SMUTEX = CreateSemaphore(NULL,0,STAND,"SAI");
//CRIAÇÃO DA THREADS DO FÃS
for (i=0; i<NFAS; ++i) {
BThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)FA, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwTheadIdprod // cating necessário
);
if (BThreads[i]) printf("FAS %d chega no STAND Id= %0x \n", i, dwTheadIdprod);
}
//CRIAÇÃO DAS THREADS DOS DEMONSTRADOR
for (i=0;i<NDEMONSTRADOR; ++i){
CThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)DEMONSTRADOR, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIdcons // cating necessário
);
if (CThreads[i]) printf("DEMONSTRADOR %d criada Id= %0x \n", i,
dwThreadIdcons);
}
//APARGA A REFERENCIA DAS THEADS
dwRetprod = WaitForMultipleObjects(NFAS, BThreads,TRUE,INFINITE);
CheckForError((dwRetprod >= WAIT_OBJECT_0) && (dwRetprod < WAIT_OBJECT_0 +
NFAS));
dwRetcons = WaitForMultipleObjects(NDEMONSTRADOR, CThreads,TRUE,INFINITE);
CheckForError((dwRetcons >= WAIT_OBJECT_0) && (dwRetcons < WAIT_OBJECT_0 +
NDEMONSTRADOR));
for (i=0; i<NFAS; ++i){
GetExitCodeThread(BThreads[i], &dwExitCodeprod);
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
CloseHandle(BThreads[i]); // apaga referência ao objeto
} // for
for (i=0; i<NDEMONSTRADOR; ++i){
GetExitCodeThread(CThreads[i], &dwExitCodecons);
CloseHandle(CThreads[i]); // apaga referência ao objeto
} // for
//APAGA A REFERENCIA DOS SEMAFAROS
CloseHandle(EMUTEX);
CloseHandle(SMUTEX);
CloseHandle(SDEMONSTRADOR);
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
return EXIT_SUCCESS;
} // main
DWORD WINAPI FA(LPVOID J)
{
LONG lOldValue;
Sleep(1000); //tempo para Criação das Trheads
do{
//CONTROLA ENTRADA DOS FANS
WaitForSingleObject(EMUTEX, INFINITE);
Sleep(100);//TEMPO PARA ENTRADA DE FANS
cont++;//CONTADOR DE FANS
//SE CONTADOR FOR MENOR QUE CAPACIDADE NO STAND ENTRA
if(cont<STAND){
printf("FAN %d Entra -- %d STAND\n", J, cont);
ReleaseSemaphore(EMUTEX, 1, &lOldValue);
WaitForSingleObject(SMUTEX, INFINITE);
printf("%d FAN Saiu - LIGA para a MAE e Volta\n", J);
}
//SE CONTADOR FOR IGUAL ENTRA E ACIONA O DEMOTRADOR
if (cont==STAND){
printf("FAN %d Entra -- %d STAND\n", J, cont);
ReleaseSemaphore(SDEMONSTRADOR, 1, &lOldValue);
ReleaseSemaphore(EMUTEX, 1, &lOldValue);
WaitForSingleObject(SMUTEX, INFINITE);
printf("%d FAN Saiu - LIGA para a MAE e Volta\n", J);
Sleep(100);
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
}
//SE CONTADOR FOR MENOR FAN AGUARDA SUA VEZ
if (cont>STAND){
printf("FAN %d AGUARDANDO\n",J);
}
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
DWORD WINAPI DEMONSTRADOR(LPVOID J)
{
LONG lOldValue;
int t;
do{
WaitForSingleObject(SDEMONSTRADOR, INFINITE);
printf("%d ENTRARAM\n", cont);
printf("Fecha o STAND ASSISTI Filme 'A VIDA DE HOARE\n");
Sleep(1000);
ReleaseSemaphore(SMUTEX, STAND, &lOldValue);
cont =0;
ReleaseSemaphore(EMUTEX, 1, &lOldValue);
}while(TRUE);
_endthreadex(0);
return(0);
}
4.8.Pombo Correio
Um pombo correio leva 20 mensagens entre os locais A e B, mas só quando o número de
mensagens acumuladas chega a 20. Inicialmente, o pombo fica em A esperando que
existam 20 mensagens para carregar, e dormindo enquanto não houver. Quando as
mensagens chegam a 20, o pombo deve levar exatamente 20 mensagens de A para B, e
em seguida volta para a. Caso existam outras 20 mensagens, ele parte imediatamente;
caso contrário, ele corem de novo até que existem as 20 mensagens. As mensagens são
escritas em um post-it pelos usuários; cada usuário, quando tem uma mensagem pronta,
cola sua mensagem na mochila do pombo. Caso o pombo tenha uma mensagem pronta,
cola sua mensagem na mochila do pombo. Caso o pombo tenha partido, ele deve espera
o seu retorno para cola a mensagem na mochila. Conforme algoritmo com os comentários que se segue.
#define WIN32_LEAN_AND_MEAN
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h> // _beginthreadex() e _endthreadex()
#include <conio.h> // _getch
#define _CHECKERROR 1 // Ativa função CheckForError
#include "CheckForError.h"
// Casting para terceiro e sexto parâmetros da função _beginthreadex
typedef unsigned (WINAPI *CAST_FUNCTION)(LPVOID);
typedef unsigned *CAST_LPDWORD;
#define NMENSAGENS 20 //DEFINE A CAPACIDADE DE MENSAGENS
#define NUSUARIOS 25 //DEFINE A QUANTIDADE DE USUARIOS
#define NPOMBO 1 // DEFINE O NUMERO DE POMBO
HANDLE SPOMBO; //SEMAFARO POMBO
HANDLE EMUTEX; //SEMAFARO CONTROLA ENTRADA DOS USUARIOS
HANDLE CMUTEX; //SEMAFARO PARA COLOCAR NA MOCHILA
int cont=0;
DWORD WINAPI POMBO(LPVOID); // DECLARAÇÃO DA FUNÇÃO POMBO
DWORD WINAPI USUARIOS(LPVOID); // DECLARAÇÃO DA FUNÇÃO USUARIOS
int main()
{
HANDLE BThreads[NPOMBO]; //DECLARAÇÃO THEADS POMBO
HANDLE CThreads[NUSUARIOS]; //THEADS USUARIOS
int i;
DWORD dwThreadIdcons, dwTheadIdprod;
DWORD dwExitCodecons = 0, dwExitCodeprod = 0;
DWORD dwRetcons, dwRetprod;
//CRIAÇÃO DOS SEMAFAROS
SPOMBO = CreateSemaphore(NULL,0,NPOMBO,"POMBO");
EMUTEX = CreateSemaphore(NULL,1,1,"TIRA");
CMUTEX = CreateSemaphore(NULL,1,1,"COLOCA");
//CRIAÇÃO DAS THREADS
for (i=0; i<NPOMBO; ++i) {
BThreads[i] = (HANDLE) _beginthreadex(
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
NULL,
0,
(CAST_FUNCTION)POMBO, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwTheadIdprod // cating necessário
);
if (BThreads[i]) printf("PONBO %d Id= %0x \n", i, dwTheadIdprod);
}
//CRIAÇÃO DAS THREADS
for (i=0;i<NUSUARIOS; ++i){
CThreads[i] = (HANDLE) _beginthreadex(
NULL,
0,
(CAST_FUNCTION)USUARIOS, // casting necessário
(LPVOID)i,
0,
(CAST_LPDWORD)&dwThreadIdcons // cating necessário
);
if (CThreads[i]) printf("USUARIOS %d criada Id= %0x \n", i, dwThreadIdcons);
}
//APARGA A REFERENCIA DAS THEADS
dwRetprod = WaitForMultipleObjects(NPOMBO, BThreads,TRUE,INFINITE);
CheckForError((dwRetprod >= WAIT_OBJECT_0) && (dwRetprod < WAIT_OBJECT_0 +
NPOMBO));
dwRetcons = WaitForMultipleObjects(NUSUARIOS, CThreads,TRUE,INFINITE);
CheckForError((dwRetcons >= WAIT_OBJECT_0) && (dwRetcons < WAIT_OBJECT_0 +
NUSUARIOS));
for (i=0; i<NPOMBO; ++i){
GetExitCodeThread(BThreads[i], &dwExitCodeprod);
CloseHandle(BThreads[i]); // apaga referência ao objeto
} // for
for (i=0; i<NUSUARIOS; ++i){
GetExitCodeThread(CThreads[i], &dwExitCodecons);
CloseHandle(CThreads[i]); // apaga referência ao objeto
} // for
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
//APAGA A REFERENCIA DOS SEMAFAROS
CloseHandle(SPOMBO);
CloseHandle(CMUTEX);
CloseHandle(EMUTEX);
printf("\nAcione uma tecla para terminar\n");
_getch(); // // Pare aqui, caso não esteja executando no ambiente MDS
return EXIT_SUCCESS;
} // main
DWORD WINAPI USUARIOS(LPVOID J)
{
LONG lOldValue;
Sleep(1000);//TEMPO PARA CRIAÇÃO DAS THREADS
do{
//CONTROLA A ENTRADA DOS USUARIOS
WaitForSingleObject(CMUTEX, INFINITE);
Sleep(100);//DA UM TEMPO PARA CADA USUARIO
cont++;
//SE CONTADOR FOR MENOR QUE MENSAGEM USUARIO COLA A MENSAGEM
if(cont<NMENSAGENS){
printf("Usuario %d Cola Mensagem -- %d na Mochila\n",J, cont);
//ACORDA UM USUARIO
ReleaseSemaphore(CMUTEX, 1, &lOldValue);
}
//COLOCA A MENSAGEM E ACORDA O POMBO
if (cont==NMENSAGENS){
printf("Usuario %d Cola Mensagem -- %d na Mochila\n",J, cont);
printf("%d Coladas na Mochila\n",cont);
//ACORDA O POMBO
ReleaseSemaphore(SPOMBO, 1, &lOldValue);
}
}while(TRUE);
_endthreadex(0);
return(0);
} // BoxFunc
DWORD WINAPI POMBO(LPVOID J)
{
LONG lOldValue;
int t;
Sleep(1000); //TEMPO PARA CRIAÇÃO DAS THREADS
FUNDAÇÃO EDUCACIONAL DE MONTES CLAROS FACULDADE DE CIÊNCIA E TECNOLOGIA DE MONTES CLAROS
DEPARTAMENTO DE ENGENHARIA DE COMPUTAÇÃO CURSO DE ENGENHARIA DE COMPUTAÇÃO
do{
printf("Pombo Dormindo\n");
//POMBO ESPERA SER ACIONADO
WaitForSingleObject(SPOMBO, INFINITE);
printf("Acorda o Pombo\n");
printf("Pombo Sai de A para B\n");
printf("%d USUARIOS AGUARDANDO\n",NUSUARIOS);
Sleep(1000);//TEMPO PARA VIAGEM DO POMBO
printf("Pombo sai de B para A\n");
printf("POMBO CHEGA\n");
cont=0; //ZERA O CONTADOR E REINICIA A COLAGEM DA MENSAGEM
//ACORDA O USUARIOS APOS A CHEGADA DO POMBO
ReleaseSemaphore(CMUTEX, 1, &lOldValue);
}while(TRUE);
_endthreadex(0);
return(0);
}//BoxFunc
5. CONCLUSÃO
Percebe-se a importância dos semáforos na implementação de processos com recursos
compartilhando, confirmando sua eficiência e conseguindo satisfazer as quatros
condições. Com essa pratica foi possível dar um fechamento na aprendizagem do
conteúdo lecionado, dando uma aprofundada no conhecimento.
Para encontrar a lógica a ser usada em cada problema deu um pouco de trabalho mas a
implementação dos códigos fluíram muito bem. Todas os problemas implementados
executaram sem erros e deram uma reposta satisfatória com relação aos problemas
propostos, que neste trabalho o uso do semáforo mostrou-se bastante dinâmico
percebendo que pode ser usadas em diversas situação e problemas que poderá surgir.
6. BIBLIOGRAFIA
FILHO, Constantino Seixas; Szuster, Marcelo. Programação Multithreaded em ambiente
Windows NT© - Uma Visão de Automação. 1999.
MACHADO, Francis Berenger; MAIA, Luiz Paulo. Arquitetura de Sistemas
Operacionais. Ed. 4. LTC Editora. 2007. 304p.