A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Threads Bauke A. Dijkstra Lucas Alves Allan F. Furukita.

Apresentações semelhantes


Apresentação em tema: "Threads Bauke A. Dijkstra Lucas Alves Allan F. Furukita."— Transcrição da apresentação:

1 Threads Bauke A. Dijkstra Lucas Alves Allan F. Furukita

2 Threads Threads, como processos são mecanismos para permitir um programa fazer mais de uma coisa ao mesmo tempo Como processo as threads aparentam correr simultaneamente O Linux kernel interrompe cada thread de tempo em tempo para dar chance de outros executar Conceitualmente uma threads está dentro do processo

3 Quando é executado um programa, é criado um processo e dentro desse é criado uma única thread que pode criar outras threads Ao criar uma nova thread nada é copiado, pois eles já compartilham a mesma memória, espaço, descrição, e outros recursos do sistema Se uma thread mudar o valor de uma variável a thread subsequente ira ver o valor alterado GNU/Linux implementa o POSIX thread API, todas funções e tipo de data são declarados no cabeçalho do arquivo Como a pthread não esta incluido na biblioteca padrao de C, para compilar você deve adicionar –lpthread pois ela esta na libpthread

4 Criação de threads Cada thread possui sua ID Na criação em a thread executa a thread function, quando retorna algum valor é porque ela existe Em C e C++ usam o tipo pthread_t A função pthread_create possui 4 parametros, (id, atributo, ponteiro da função, argumento) A chamada de pthread_create retorna imediatamente e a thread original continua a executar as instruções seguindo a chamada, enquanto a nova thread começa a função thread Seu programa não pode depender da ordem de execuções das threads

5

6 Como passar dados para Threads? É utilizado o argumento para a passagem de dados Normalmente é definido uma estrutura para cada função thread que possui os parametros que é esperado

7 Juntando Threads É feita a partir da função pthread_join, que possui dois parâmetros. O id da thread que tem que esperar e um ponteiro que irá receber o retorno da thread quando terminar Caso não seja necessário o valor de retorno utiliza o NULL Caso seja diferente de NULL o valor de retorno será armazenado no local apontado pelo argumento

8 Mais sobre Thread’s Ids A função pthread_self retorna o a ID da thread que foi chamada A função pthread_equal serve para comparar os ID das threads

9 Atributos de Threads Providencia um mecanismo para melhorar o comportamento da thread Você pode criar e customizar atributos de objeto da thread para especificar outros valores para os atributos Para especificar uma thread customizada você deve, criar pthread_attr_t, chamar pthread_attr_init, modificar o atributos de objeto da thread para conter o que é desejado, passar um ponteiro para o objeto quando chamar pthread_create, chamar pthread_attr_destroy

10 Um unico atributos de objeto da thread pode ser usado para começar varias threads Não é necessário deixar o atributos de objetos da thread ao redor depois que as threads foi criada Uma Thread pode ser declarada como joinable thread ou como detached thread Joinable thread não é limpada automaticamente quando terminada já a detached thread limpa automaticamente e por isso essa não pode ser sincronizada com outra thread Para escolher o estade detach no atributo de objeto da thread utiliza pthread_attr_setdetachstate sendo o primeiro parametro um ponteiro para o atributo de objeto da thread, e o segundo o estado desejado de detach

11 Cancelamento da Thread A função utilizada é a pthread_cancel, passando a ID da thread Ela pode ser juntada depois de cancelada Para liberar seus recursos ela deve ser juntada Temos três estados em relação ao cancelamento das threads Cancelamento assíncrono Cancelamento síncrono (padrão) Incancelável

12 Threads Síncrona e Assíncrona Uma thread cancelável assíncrona pode ser cancelada em qualquer ponto da execução, já a síncrona pode ser cancelada em pontos específicos da execução Para deixar uma thread cancelável assíncrona utilize pthread_setcanceltype, que afeta a thread que chamou a função. pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); Para criar pontos de cancelamento utiliza-se o pthread_testcancel

13 Seções Críticas Incancelável A thread pode desabilitar o cancelamento usando a função pthread_setcancelstate pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL); Usando a função acima habilita a implementação de seções críticas Seções críticas é uma seqüência de códigos que não pode ser cancelado enquanto não estiver pronto

14 Quando usar cancelamento da Thread No geral não é aconselhável utilizar cancelamento de uma thread para finalizar a execução de uma thread, exceto em circunstancias incomuns. A melhor estratégia é indicar a thread que deve sair e esperar ela terminar de maneira normal.

15 Dados específicos da Thread As threads pertencentes a um processo compartilham os dados do processo. Esse compartilhamento de dados fornece um dos benefícios da programação multithreads. Em certas circunstancias, cada thread poderia precisar de sua própria copa de certos dados. Você pode criar quantos dados específicos da thread que quiser, sendo do tipo void*

16 Cada item é referenciado por uma chave Para criar uma nova chave é usado a função pthread_key_create O primeiro argumento é um ponteiro para a variavel pthread_key_t O segundo argumento para pthread_key_t é uma função de limpeza, pode-se passar null caso não precise de uma função de limpeza.

17 Depois da chave ser criada, cada thread pode definir seu valor de thread-específico correspondendo a chave chamando pthread_setspecific. O primeiro argumento é a chave O segundo argumento é o valor do void* thread-específico para armazenar Para recuperar os dados do thread-específico, se chama pthread_getspecific, passando a chave como seu argumento.

18 Cleanup Handlers São funções chamadas quando a thread é terminada ou cancelada. Ela é útil por ser capaz de especificar funções de limpeza sem criar um novo dado de thread específico que esta duplicado pra cada thread. O GNU/LINUX te da esse recurso com esse proposito. O handler toma um parâmetro void* e o valor do argumento é dado quando o handler é registrado.

19 Um Cleanup Handler é uma medida temporária, usada para desalocar um recurso somente se a thread é fechada ou cancelada. Caso a thread não sair ou for cancelada, o cleanup handler deve ser removido e o recurso desalocado explicitamente. Para registrar um cleanup handler, deve-se chamar pthread_cleanup_push, passando um ponteiro para a função de limpeza e o valor do argumento void*

20 A chamada para pthread_cleanup_push deve ser equilibrada por uma chamada correspondente para pthread_cleanup_pop, que cancela o registro de limpeza handler. Como uma conveniência pthread_cleanup_pop leva um argumento int flag Se a flag é diferente de zero, a ação de limpeza é realizada, uma vez que não é registrada.

21 Thread Cleanup em C++ Quando os objetos saem do escopo, C++ garante que os destructors sejam chamados para essas variáveis automáticas, fornecendo um código de limpeza que é chamado não importando como o bloco foi encerrado. Se uma thread chama pthread_exit, a linguagem C++ não garante que os destructors sejam chamados para todas variáveis automáticas A melhor forma para recuperar essa funcionalidade é usar pthread_exit no nível superior da função thread jogando uma exceção especial

22 Sincronização e Sessões Críticas Programar com threads é muito complicado, por causa da sua concorrência. É impossível saber quando o sistema irá agendar e executar uma thread. Para fazer um “debbuging” é complicado, pois você pode executar o programa e funcionar, mas na próxima ele pode falhar.

23 Condições de Corrida A causa definitiva da maioria dos problemas que envolvem threads é que estes estão acessando os mesmos dados. Se uma thread usa parcialmente uma estrutura de dados enquanto outra acessa a mesma estrutura, problemas são suscetíveis de acontecer. Quando uma thread fica agendada mais ou menos frequentemente que outra pode ocorrer um erro conhecido como condição de corrida.

24

25 A depuração de programas que contenham condições de corrida não é nada simples. Os resultados da maioria dos testes não apresentam problemas, mas em algum momento algo estranho pode acontecer.

26 Sessões Críticas O problema de evitar condições de disputa pode ser formulado de um modo abstrato. Durante uma parte do tempo, um processo está ocupando fazendo coisas que não levam a condições de disputa. Porém, algumas vezes ele precisa ter acesso à memória ou outra coisas que pode ocasionar disputas. Na parte do programa onde há acesso à memória compartilhada é chama ou sessão critica ou região crítica

27 Porém, mesmo que evite-se as condições de disputa, é necessário satisfazer 4 condições para chegar a uma boa solução: 1.2 Processos nunca 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.

28 Exclusão mútua É um modo de assegurar que outros processos sejam impedidos de usar uma variável ou um arquivo compartilhado que já estiver em uso por um processo.

29

30 Semáforos É uma variável especial que tem como função o controle de acesso a recursos compartilhados. O valor de um semáforo indica quantas threads podem ter acesso a um recurso compartilhado. Edsger Dijkstra, criador do semáforo propôs a existência de duas operações, down e up (ou sleep e wakeup, respectivamente).

31 Down: Verifica se o valor do semáforo é maior que zero. Se sim, decrementará o valor e prosseguirá. Se o valor for zero, o processo será posto para dormir, sem terminar o down, pelo menos por enquanto. Up: Incrementa o valor de um dado semáforo. Se um ou mais processos estivessem dormindo naquele semáforo, um deles seria escolhido pelo sistema e seria dada a permissão para terminar seu down.

32 Mutexes Um mutex (abreviação de mutual exclusion, exclusão mútua) é uma versão simplificada de semáforo e só é adequado para gerenciar a exclusão mútua de algum recurso ou parte de código compartilhada.

33 Mutexes são fáceis de implementar e eficientes, o que os torna especialmente úteis em pacotes de threads implementados totalmente no espaço do usuário. Um mutex é uma variável que tem dois estados (desimpedido ou impedido) e consequentemente, somente 1 bit é necessário para representá-lo.

34 Quando um thread precisa ter acesso a uma região crítica, ele chama mutex_lock. Se o mutex estive desimpedido, a chamada prosseguirá. Por outro lado, se o mutex já estiver impedido, o thread que chamou mutex_lock, permanecerá bloqueado até que o thread na região crítica termine e chame mutex_unlock. Se vários threads estiverem bloqueados sobre o mutex, um deles será escolhido e liberado para adquirir a trava.

35

36 Barreiras Algumas aplicações são divididas em fases e têm como regra que nenhum processo pode avançar para a próxima fase até que todos os processos estejam prontos a fazê-lo. Isso pode ser conseguido por meio da colocação de uma barreira no final de cada fase. Quando alcança a barreira, um processo permanece bloqueado até que todos os processos alcancem a barreira.

37

38 Implementação de thread GNU/Linux A implementação de threads POSIX no GNU/Linux é diferente da implementação em outros sistemas UNIX. No GNU/Linux threads são implementados como processos. Quando se chama pthread_create para criar uma nova thread, o Linux cria um novo processo para executar a thread

39 Manipulação de sinais O comportamento de interação entre sinais e threads variam de um sistema tipo UNIX para outro. No GNU/Linux o comportamento é ditado por um fato que as threads são implementadas como processos. Uma vez que cada thread é um processo separado, e porque um sinal é emitido para determinado processo, não há ambiguidade sobre qual thread recebe o sinal.

40 Normalmente sinais são enviados de fora do programa ao processo correspondente ao thread principal. Em um programa multithread, é possível para um thread enviar um sinal específico para outro thread, usando a função pthread_kill. Passando o ID da thread como seu primeiro parâmetro e um numero de sinais como seu segundo parâmetro.

41 Chamada de Sistema clonada A chamada de sistema clonada do Linux é uma forma generalizada de fork e pthread_create que permite especificar os recursos compartilhados entre o processo de chamada e o novo processo criado. O clone requer que especifique a região da memória para a execução da pilha que o novo processo use. Para criar novos processos use fork Para criar novas threads use pthread_create

42 Processos x Threads Todos threads em um programa deve rodar o mesmo executável. Um processo filho pode rodar um executável diferente chamando uma função exec. Um thread errante pode prejudicar outros threads no mesmo processo porque compartilham o mesmo espaço de memória virtual e outros recursos. Um processo errante não prejudica pois cada processo tem uma cópia do espaço de memória do programa.

43 Threads deve ser usada em sistema paralelo de grão fino, em que o problema pode ser dividido em várias tarefas semelhantes. Processo deve ser usado em sistema paralelo de grão grosso. Compartilhamento de dados entre threads é trivial porque threads compartilham a mesma memória. O compartilhamento de dados entre os processos requer o uso de mecanismos de IPC.


Carregar ppt "Threads Bauke A. Dijkstra Lucas Alves Allan F. Furukita."

Apresentações semelhantes


Anúncios Google