Upload
rafaelov
View
4.509
Download
2
Embed Size (px)
DESCRIPTION
Apresentação do artigo THREADS: O PROBLEMA DOS LEITORES E ESCRITORES IMPLEMENTADO EM C#.
Citation preview
Threads: O problema dos Leitores e Escritores Implementado em C#Autores:
Daniel Ramon Silva Pinheiro
Danilo Santos Souza
Rafael Oliveira Vasconcelos
Orientadora:
Maria de Fátima A. S. Colaço
ThreadsÉ uma forma de um processo dividir-se em duas ou mais
tarefas que podem ser executadas simultaneamente
Nos hardwares equipados com múltiplos núcleos, as linhas de execução de uma thread, podem ser executadas paralelamente,
Já nos hardwares com um único núcleo, cada linha de execução é processada de forma aparentemente simultânea. Neste caso a mudança entre uma linha e outra é feita de forma tão rápida que para o usuário isso está acontecendo paralelamente.
Threads e Processos – DiferençasMódulos executáveis de um processo
Um módulo executável é um conjunto de instruções de um programa que devem ser seguidos para a conclusão do mesmo.
Processos são módulos separados e carregáveis
Threads não são carregados. Threads são iniciados dentro de um processo (Pai).
O processo Pai pode iniciar várias threads ao mesmo tempo.
Threads: O Universo dos modelos de processosExistem 2 conceitos para os modelos:
Primeiro: Modo de ver um processo:
• Espaço de endereçamento (código e os dados de programa). Alguns recursos alocados (arquivos abertos, processos filhos).
• Objetivo: Agrupar todos eles em forma de processos para facilitar o gerenciamento dos recursos.
Threads: O Universo dos modelos de processosSegundo: Thread de execução (Thread):
• Contador de programa (controla qual instrução da thread deverá ser executada em seguida pelo núcleo)
• Registradores (com as variáveis de trabalho atuais)
• Pilha estruturada pelo conjunto de procedimentos chamados, mas ainda não concluídos (informa o histórico da execução).
Threads e Processos – DiferençasOs dois conceitos citados (Processo e Thread de
execução) são importantes, pois delimitam os conceitos entre threads e processos, que apesar de semelhantes, são conceitos diferentes.
A característica que os threads acrescentam ao conceito de processos é a permissão de múltiplas execuções ocorrerem em um mesmo processo de forma independente uma das outras.
Threads: O Universo dos modelos de processos• Importância dos modelos (Processo e Thread de
execução):
• Delimitam os conceitos entre threads e processos, que apesar de semelhantes, são conceitos diferentes.
• A característica que os threads acrescentam ao conceito de processos é a permissão de múltiplas execuções ocorrerem em um mesmo processo de forma independente uma das outras.
Threads: Sistemas monothread e multithread• Sistemas monothread: Sistemas que suportam apenas
uma única thread em execução por vez.
• Sistemas multithread: Sistemas que suportam mais de uma por vez.
• Questão: Qual a diferença de ter várias threads sendo executadas em um único processo (multithread), e vários processos sendo executados em um computador?
Threads: O Universo dos modelos de processos• Resposta:
• Nos Sistemas multithread várias threads estão compartilhando um mesmo espaço de endereçamento na memória, assim como os recursos alocados pelo processo criador da thread.
• Já nos Sistemas monothread os processos compartilham um espaço físico de memória.
Threads: Tipos (Usuário e Núcleo)
• Thread de usuário:
• Todos os pacotes e controles de threads estão no espaço do usuário. O núcleo não sabe que existem essas threads.
• As threads serão tratadas de forma simples (monothread). Mesmo que existam vários núcleos (multiprocessamento), somente os processos é que serão executados paralelamente e não as threads.
• Para o núcleo será apenas mais uma linha de execução do processo.
Threads: Tipos (Usuário e Núcleo)
• Thread de usuário:
• Vantagem Principal:
• Versatilidade, pois elas funcionam tanto em sistemas que suportem ou não o uso de threads
• Implementação interna ao processo criador da thread.
• Sistema operacional não irá interferir nesta criação, desta forma o sistema executará a thread como se fosse apenas mais uma linha de execução do processo.
Threads: Tipos (Usuário e Núcleo)
• Thread de núcleo:
• Grande vantagem: Caso uma thread seja bloqueada, as outras threads que forem geradas pelo mesmo processo poderão dar continuidade às suas linhas de execução, sem a necessidade da thread bloqueada concluir suas linhas de execução.
• O núcleo sabe da existência das threads
• O processo não precisará de tabela para gerenciar as threads, o núcleo se encarregará de tudo, os processos apenas realizam chamadas ao núcleo para a manipulação de suas threads.
Threads: Tipos (Usuário e Núcleo)
• Thread de núcleo:
• Chamadas ao sistema possuem um custo maior se comparadas com as chamadas que um sistema de threads de usuário realiza.
• Sistemas utilizam-se da ‘reciclagem’ de threads, desta forma, quando uma thread é destruída, ela é apenas marcada como não executável, sem afetar sua estrutura.
• Conseqüência: A criação de uma nova thread será mais rápida, com sua estrutura já montada, basta apenas a atualização de suas informações.
Threads: Comunicação entre as Threads• Com freqüência as threads precisam trocar informações
entre si para continuar suas linhas de execução.
• Como elas compartilham um espaço de endereçamento comum isso torna-se um pouco mais fácil, entretanto ainda é necessário um controle para evitar embaraços entre elas.
• Esses embaraços geralmente ocorrem quando elas acessam uma variável compartilhada ao mesmo tempo, ou seja, dentro de uma região crítica.
Threads: Comunicação entre as Threads• Região Crítica:
• Região de memória compartilhada que acessa um recurso que está compartilhado e que não pode ser acessado concorrentemente por mais de uma linha de execução
• Como o próprio nome já diz, por ser uma área crítica necessita de cuidados para que não hajam problemas futuros devido à má utilização da mesma.
Threads: Comunicação entre as Threads• Região Crítica:
• Condição de disputa:
• Conjunto de recursos que deve ser compartilhado entre processos no qual, em um mesmo intervalo tempo, dois ou mais processos tentem alocar uma mesma parte de um mesmo recurso para poder utilizá-lo. Nesta hora que ocorre o problema do controle de disputa.
Threads: Comunicação entre as Threads• Região Crítica:
• Condição de disputa:
• Necessidade de encontrar uma forma de bloquear que outros processos usem uma área compartilhada que esteja sendo usada até que ela seja liberada pelo processo que a esteja utilizando.
• A essa solução denomina-se exclusão mútua.
Threads: Comunicação entre as Threads• Exclusão Mútua:
• Solução encontrada para evitar que dois ou mais processos ou threads tenham acesso simultaneamente a alguma região crítica de algum recurso que esteja compartilhado.
• Para que a solução seja válida, devem ser satisfeitas quatro condições para que os processos e threads concorrentes à mesma região crítica sejam executados de forma eficiente e corretamente.
Threads: Comunicação entre as Threads• Exclusão Mútua (As Quatro Condições):
1. Nunca dois processos podem estar simultaneamente em suas regiões críticas;
2. Nada pode ser afirmado sobre a velocidade ou sobre o número de CPUs;
3. Nenhum processo executando fora de sua região crítica pode bloquear outros processos;
4. Nenhum processo deve esperar eternamente para entrar em sua região crítica;
Threads: Problemas com o uso de threads• O uso de threads acarreta alguns problemas como:
• Os de acesso à região crítica
• Dificuldade de implementação
• Dificuldade de depuração do código
• Deadlock e o Starvation
Threads: Problemas com o uso de threads• Deadlock:
• Ocorre quando há um impasse e dois ou mais processos ou threads ficam impedidos de continuar suas execuções, ou seja, ficam bloqueados para sempre.
• Starvation:
• Ocorre quando um processo ou thread nunca é executado, pois processos ou threads de maior importância sempre tomam a posse do núcleo fazendo com que os de menores prioridades nunca sejam executados.
O Problema dos Leitores e EscritoresModela o acesso a uma Base de Dados.
Ocorre em Processos Concorrentes.
Processos Leitores somente lêem a Região Crítica.
Processos Escritores alteram a Região Crítica
Acesso simultâneo para Processos Leitores pelo fato de não alterarem a Região Crítica.
Acesso Exclusivo para Processo Escritor pelo fato de alterar a Região Crítica.
Para melhor entendimento a seguir, considere a Base de Dados como Região Crítica.
O Problema dos Leitores e Escritores Vários Processos visando a mesma Base de Dados.
Base
de
Dados
PL
PL
PLPE
PL – Processos LeitoresPE – Processos Escritores
Esperando Acesso a Base de DadosAcessando a Base de Dados
1
2
4
3
O Problema dos Leitores e Escritores Enquanto existir pelo menos um Processo Leitor acessando a
Base de Dados, o acesso para a chegada de novos Processos Leitores será concedido.
Base de
Dados
PL
PL
PL
Base de
Dados
PL
PL
PL
1
2
4
PL
PL
PL
1
2
4
6
9
7
PL – Processos LeitoresPE – Processos Escritores
Esperando Acesso a Base de DadosAcessando a Base de Dados
O Problema dos Leitores e Escritores
Base de
Dados
PL
PL
Base de
Dados
PL
PL
PL
1
2
PL
PL
PE
1
2
4
6
9
7
Enquanto existir pelo menos um Processo Leitor acessando a Base de Dados e existir Processo Escritor em espera, a chegada de Processos Leitores para acesso será concedido e o Processo Escritor continuará esperando pelo acesso.
PE 4
PL – Processos LeitoresPE – Processos Escritores
Esperando Acesso a Base de DadosAcessando a Base de Dados
O Problema dos Leitores e Escritores Se sempre chegarem Processos Leitores e existir pelo menos
um Processo Leitor acessando, o Processo Escritor pode chegar a um problema denominado Starvation, que é a possibilidade do Processo Escritor nunca acessar a Base de Dados pelo fato de sempre estarem chegando Processos Leitores.
O Problema dos Leitores e Escritores Se não existir nenhum Processo tanto Leitor quanto Escritor
acessando a Base de Dados, o acesso é concedido normalmente.
Base de
Dados
Base de
Dados
PE 4
PL – Processos LeitoresPE – Processos Escritores
Esperando Acesso a Base de DadosAcessando a Base de Dados
O Problema dos Leitores e Escritores
Base
de
Dados
PL
PL
PEPE
1
2
4
3
Processo Escritor faz com que outros Processos esperem pelo acesso.
PL – Processos LeitoresPE – Processos Escritores
Esperando Acesso a Base de DadosAcessando a Base de Dados
O Problema dos Leitores e Escritores Pseudocódigo abordando solução
semaphore mutex = 1; // controla acesso a região criticasemaphore db = 1; // controla acesso a base de dadosint rc = 0; // número de processos lendo ou querendo ler
void writer(void){
while (TRUE) { // repete para semprethink_up_data(); // região não criticadown(&db); // obtém acesso exclusivowrite_data_base(); // atualiza os dadosup(&db); // libera o acesso exclusivo
}}
Variáveis
Procedimento do Escritor
O Problema dos Leitores e Escritores
void reader(void){
while(TRUE) { // repete para sempredown(&mutex); // obtém acesso exclusivo a região criticarc = rc + 1; // um leitor a mais agoraif (rc == 1) down(&db); //se este for o primeiro leitor bloqueia a base de
dadosup(&mutex) // libera o acesso a região critica read_data_base(); //acesso aos dadosdown(&mutex); // obtém acesso exclusivo a região criticarc = rc -1; // menos um leitorif (rc == 0) up(&db); // se este for o último leitor libera a base de dadosup(&mutex) // libera o acesso a região criticause_data_read(); // utiliza o dado
}}
Procedimento do Leitor
O Problema dos Leitores e Escritores Vantagens
Evita Espera Ocupada.
Melhor uso da Multiprogramação.
Desvantagem
Pode ocasionar Starvation.
Threads no C#O C# provê vários recursos para utilização de threads
Iniciar threads
Bloqueio simples
Mutex, semáforo
Monitores
Prioridade
Manipulação de estados
Uso do namespace System.Threading
Threads no C#: Criando e IniciandoÉ bastante simples criar e iniciar uma thread
Basta criar uma variável do tipo Thread e passar no construtor o método que será executado
ThreadStart delegado = new Thread Start(metodo);
Thread t = new Thread(delegado;)
Ou
Thread t = new Thread( ThreadStart(metodo) );
Iniciar a thread é bastantes intuitivo
t.Start();
Threads no C#: Exemplo Olá Mundoclass Ola_Mundo {
static void Main() {
Thread t = new Thread(new ThreadStart(Imprime));
t.Start();
}
static void Imprime() {
Console.WriteLine("Ola Mundo!");
}
}
Threads no C#: SincronizaçãoA forma mais simples de sincronizar threads é utilizando o
método Join
Este método faz o bloqueio do programa até que a thread seja executada por completo, sendo então liberado para prosseguir com as demais instruções.
Garante que o fluxo de execução só prosseguirá quando a thread terminar sua execução.
Esta é uma forma bastante simples da manter a sincronização entre threads, porém anula a execução paralela, principal motivo para o uso de threads.
Threads no C#: Método Joinclass Ola_Mundo {
static void Main() {
Thread t = new Thread(new ThreadStart(Imprime));
t.Start();
t.Join();
Console.WriteLine("Fim do programa.");
}
static void Imprime() {
Console.WriteLine("Ola Mundo!");
}
}
Threads no C#: Bloqueio LockÉ a formais de bloqueio mais simples e permite obter a posse
de um objeto, bloqueando um bloco de código
Evita a condição de corrida e garante a exclusão mútua
Caso outra thread tente realizar o bloqueio de um objeto que se encontra bloqueado, a thread será bloqueada pelo sistema operacional e só poderá continuar quando o objetivo for liberado
Por ser a forma mais simples de realizar um bloqueio, também é mais rápida.
Threads no C#: Bloqueio Lock
lock (contador) {
contador++;
Console.WriteLine(contador);
}
Threads no C#: Classe MutexA classe mutex funciona de forma parecida com o bloqueio
lock
Por não realizar o bloqueio por blocos de código, permite que tanto o bloqueio como o desbloqueio seja realizado em diferentes regiões do código com uso dos métodos WaitOne e ReleaseMutex
Garante a exclusão mútua de uma região crítica
A tentativa de bloqueio de um objeto já bloqueado é análoga a forma anterior
Threads no C#: Classe Mutex
mutex.WaitOne();
//bloqueio realizado
contador++;
Console.WriteLine(contador);
mutex.ReleaseMutex();
//recurso liberado
Threads no C#: Classe SemaphoreÉ uma extensão da classe mutex
Como principais características permite que um ou mais processos entrem na região crítica e que o bloqueio realizado por uma thread possa ser desfeito por outra thread, recurso que pode ser útil em determinados problemas, como no problema dos leitores e escritores.
Na inicialização deve ser informado o valor máximo e inicial do semáforo
Caso o semáforo seja inicializado com valor 1, tem o mesmo funcionamento do mutex
Threads no C#: Classe Semaphore
semaforo.WaitOne();
contador++;
Console.WriteLine(contador);
semaforo.Release();
Threads no C#: Classe MonitorO C# oferece ainda a classe Monitor que provê outras
funcionalidades como:
Sinalizar e esperar por uma sinalização de outra thread
Pulse ou PulseAll e Enter
Outro recurso interessante é o TryEnter que como o próprio nome diz, tenta obter o acesso ao objeto, caso não seja possível retorna o valor false
O método Enter funciona de maneira semelhante aos já mencionados
É 33 vezes mais rápida que a classe Mutex
Threads no C#: Outros recursosNomear a thread
Atribuir prioridade às threads
Lowest, BelowNormal, Normal, AboveNormal e Highest
Indicar se a thread deve ser executada em segundo plano
Adormecer por um tempo determinado – Sleep(x)
Suspender - Suspend
Retomar - Resume
Interromper – Interrupt
Abortar - Abort
Threads no C#: Os leitores e escritoresPrograma desenvolvido com a solução para o problema dos
leitores e escritores