Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Vamos falar sobre uma biblioteca de paralelismo,
- de nome pthread.
- Nos primeiros softwares não se pensava em permitir o compartilhamento de memória entre dois processos
- pois casos como esse normalmente se enquadravam como erros e deviam ser evitados.
- Algum tempo depois disso com o aumento da capacidade de processamento dos processadores e do surgimento dos
- computadores multi-processados, criou-se a idéia dos "processos leves" que poderiam representar uma fração
- de um processo maior, e pela primeira vez realizar processamentos de maneira paralela.
- Os processos leves, também chamados de "threads" ou em português "seguimentos" passaram então
- a compor programas que agora possuem vários processos simuntâneos, e todos compartilhando o mesmo campo de memória,
- e trabalhando um mesmo problema.
- Nessa aula de hoje estudaremos um tipo especifico de programação com uso de threads,
- que serão as pthreads que é uma biblioteca em linguagem C para uso nos compiladores para linux.
- Vantagens do uso de pThreads:
- - portabilidade de software // Funcionam em várias arquiteturas
- - esconder latência
- - e fácil de usar
- // Obs eu não consegui anotar todas as vantagens e nem sei se as que anotei estão 100% corretas.
- // Mas deixarei aí de qualquer forma.
- Abaixo especificarei detalhes técnicos do uso de pthreads em código C
- que o professor nós sugeriu práticar antes do próximo trabalho prático.
- A biblioteca a ser inclusa para seu uso:
- #include <pthread.h>
- A função construtora que lança uma thread para ser processada:
- int pthread_create
- (
- pthread_t* thread_handle, // Identificador retornado pelo criador de threads.
- attr, // Parâmetro de configuração da thread -> O uso dessa entrada ainda não nós será explicado.
- ponteiro para funcao, // Toda thread deve possuir uma função que reja seu funcionamento (obviamente).
- parametro em forma void* // Essa função estará prepara para receber um e somente um argumento, que
- // pode ser estruturado em forma de um ponteiro para struct para agrupar mais parâmetros.
- );
- A função acima é a função básica, e com ela já é possível a criação de uma thread, e naturalmente uma vez que
- a função descritiva da thread termine a thread também será encerrada.
- É importante notar que o meio pelo qual uma thread pode retornar uma saída não é como as demais funções,
- os únicos retornos possíveis são através do uso de ponteiros e arranjos passados como parâmetros dentro do struct de entrada.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Uma vez que uma thread tenha se iniciado, pode ser útil saber quando ela vai terminar,
- muitas vezes parte do processamento só pode ocorrer uma vez que uma thread encerre seu funcionamento.
- Para isso existe a função:
- int pthread_join
- (
- pthread_t thread, // Id da thread que voce quer se juntar que é retornado pela função construtora da mesma.
- );
- Uma vez chamada essa função o código só seguirá em frente quando a thread especificada for encerrada.
- Permitindo a sincronização de dois ou mais processos.
- Um meio para encerrar uma thread que esteja em funcionamento é utilizar a função abaixo:
- int pthread_exit(0)
- Ao invés de simplismente retornar a função. Imagino que este metodo seja mais correto,
- mas ainda não sei bem porquê.
- Nota importante do professor:
- Não use ponteiros recebidos por parametro em uma thread com frequencia!
- a cada acesso a um ponteiro deste você estará acessando a memória de outro processador
- gerando um grande overhead desnecessáriamente. Tenha preferencia por cópiar os dados necessários
- para variaveis locais de fácil acesso.
- CONCEITO:
- Condição de corrida é a caracteristica intrinsica das threads que às impede de editar uma mesma variável
- de maneira previsível. Ou seja, se há duas threads acessando a mesma variável não há como
- saber qual delas escreverá nesta variável por último, o que pode gerar confusão
- e portanto deve ser sempre tratado para evitar erros.
- Uma solução para este tipo de problema é a "travagem" dos acessos a uma variável, no intuito de garantir
- o monopólio de seu acesso a uma única thread.
- Essa solução já é facilitada pelo uso de uma conjunto de funções chamadas mutex
- cujas principais seguem abaixo:
- pthread_mutex_init( variavel global) // inicia uma variável.
- pthread_mutex_lock( var global ) // Essa função pode ser usada por uma thread para travar uma variável em seu monopólio.
- pthread_mutex_unlock( var global ) // Destrava a variavel permitindo então o acesso à ela por outra thread.
- // Também existem funções para se saber se uma váriavel está travada ou não antes de acessa-la, mas falaremos disso mais abaixo.
- Nota do professor:
- Se voce implementar isso na forma de um verificador constante de lock voce estará abusando do processador e disperdiçando
- tempo de processamento, portanto se possível encontre uma tarefa alternativa para ser realizada sempre que uma thread
- detectar que a variável que ela deseja acessar está travada.
- O nome desse processo de repetição é "biziwaking", apesar de só conhecer este nome de ouvido.
- Existem 3 tipos de mutex o normal o recursivo e o error check
- esses 3 tem 3 jeitos diferentes de lidar com isso
- e um problema serio eh o risco de uma thread travar a si mesma, bloqueando a variavel para sempre.
- A função "trylock" abaixo é responsável pela verificação da disponibilidade de uma váriavel,
- e se essa variável se encontrar livre ela é então travada garantindo o acesso à variável.
- int pthread_mutex_trylock(pthread_mutex_t);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Um outro meio de lidar com a sincronização de threads é utilizando uma variável de condição.
- Uma variável de condição, é usada como uma flag, que destrava o funcionamento de uma thread
- no momento em que ela for ativada, ou no caso especifico que vou mostrar abaixo
- no momento em que ela for modificada:
- Para esse propósito pode-se usar a função pthread_cond_wait()
- pthread_cond_wait( variavel global )
- Uma vez que esta função for chamada ela só retorna quando o valor da variavel global em questão for editado.
- A ativação deste flag portanto é uma variação qualquer daquela variavel, como por exemplo um incremento.
- CONCEITO:
- Barreira, eh uma estrategia de sincronizacao coletiva que eh quando voce espera todas as threads terminarem uma tarefa para continuar.
- A função pthread_cond_wait(VG) pode ser usada na criação de uma barreira. Use por exemplo uma variável X=0 para ser incrementada
- sempre que uma thread chegar no ponto de sincronização. Quando a última thread chegar, ela verá que ela é a ultima a terminar
- pelo valor na variavel incrementada, e poderá então alterar o valor da variável "VG" da função pthread_cond_wait() e liberar todas as outras para continuar o processamento.
- CONCEITO:
- Deadlock é um erro que ocorre quando duas threads impedem travam o funcionamento uma da outra de forma que
- enquanto nem uma das duas for destravada, ambas continuarão presas para sempre. Sabotando o funcionamento do programa.
- Um meio comum disso acontecer é quando dadas duas threads t1 e t2 e duas variáveis a e b que são sempre usadas juntas,
- a thread 1 da um trylock em A e simuntaneamente a thread 2 da um trylock em B, em seguida ambas as threads entram em loop aguardando
- que um trylock em B e A respectivamente às threads 1 e 2 retorne positivo.
- Ou seja, cada uma fica sem fazer nada esperando que a outra libere o lock da variável, e ficam nisso eternamente.
- Um macete para evitar isso é sempre garantir que os locks sobre um grupo de variáveis são acessados sempre na mesma ordem
- por todas as threads que às usam.
- // A aula de hoje foi isso,
- // Foi um pouco indigesta devido a grande quantidade de informações, o ideal é estudar separadamente cada uma das funções
- // citadas, e práticar o uso delas em um código C. Realmente não é um "para casa" fácil =/.
- // Também não garanto que as informações contidas nessa nota de aula especifica sejam confiáveis, eu me lembro que esta aula
- // aconteceu muito rápido e não fui capaz de copiar tudo. Por isso podem haver alguns erros no que escrevi.
- // Boa sorte nos estudos, também vou precisar.
Advertisement
Add Comment
Please, Sign In to add comment