Você está na página 1de 34

Programao C

Aula 11 Programao concorrente (threads)


Italo Valcy <italo@dcc.ufba.br>

Italo Valcy Programao em C

Licena de uso e distribuio

Todo o material aqui disponvel pode, posteriormente, ser utili ado so!re os termos da" Atribuio Creative Commons License: so no comercial - !erman"ncia da Licena

#tt$:%%creativecommons.or&%licenses%by-nc-sa%'.(%

Italo Valcy Programao em C

2 / 34

#otivao
$esempenho
Conseguir redu ir o tempo de e%ecuo dos programas em m&quinas multiprocessadas

#odelagem
$escrever o comportamento natural de algumas aplica'es (opera'es ()*, ocorr+ncia assncrona de eventos, tare,as independentes, etc-)

Italo Valcy Programao em C

3 / 34

Programao concorrente e paralela


.a programao sequencial todas as instru'es de um programa so e%ecutadas atrav/s de uma 0nica linha de e%ecuo .a programao concorrente e paralela um programa pode ser e%ecutado atrav/s de diversas linhas de e%ecuo

Italo Valcy Programao em C

4 / 34

Programao concorrente e paralela

Italo Valcy Programao em C

5 / 34

Paralelismo ,sico e l1gico

Italo Valcy Programao em C

6 / 34

Concorr+ncia com Processos


2m processo / um ,lu%o de controle sequencial e seu espao de endereamento (vari&veis, registradores, arquivos, etc-) Cada processo possui um conte%to, que deve ser salvo quando o processo / interrompido e relido quando ele ,or retomado 2m processo / uma a!strao do 3-*2m processo pode criar outros processos para reali ar atividades independentes"
fork()
Italo Valcy Programao em C
7 / 34

Concorr+ncia com Processos

Italo Valcy Programao em C

8 / 34

Concorr+ncia com Threads


4inhas de e%ecuo concorrentes Permitem m0ltiplas atividades independentes dentro de um 0nico processo Threads de um mesmo processo compartilham"
Todo o espao de endereamento, e%ceto a pilha, os registradores e o contador de programa Arquivos a!ertos *utros recursos

Italo Valcy Programao em C

9 / 34

Concorr+ncia com Threads

Italo Valcy Programao em C

10 / 34

Processos vs Threads

5onte" https"))computing-llnl-gov)tutorials)pthreads)

Italo Valcy Programao em C

11 / 34

Processos
for)*+

Para criar processos no 4inu%, deve6se usar a chamada de sistema for)*+ fork() ,a com que o processo atual se7a dividido em dois novos processos processo pai e processo filho Todas as p&ginas de mem1ria do processo original so duplicadas em uma chamada ao fork(), assim am!os, pai e ,ilho, tem acesso a todas as in,orma'es-

Italo Valcy Programao em C

12 / 34

Processos
for)*+

8alor de retorno"
.o pai" Processo ($ (P($) do ,ilho .o ,ilho" 9 ( ero)

3e o ,or:() ,alhar por algum motivo (,alta de mem1ria, muitos processos, etc-), ele no cria um novo processo, e retorna 61-

Italo Valcy Programao em C

13 / 34

Processos
for)*+ , e-em$lo
#include<stdio.h> #include<unistd.h> #include <sys/wait.h> int main() { pid_t pid; pid = fork(); if (pid<0) { printf("Erro ao criar novo processo\n"); return 1; } else if (pid == 0) { printf("Filho... PID=%d\n", getpid()); } else { printf("Pai... PID=%d\n", getpid()); wait(NULL); } printf("%d - encerrando...\n", getpid()); return 0; } Italo Valcy Programao em C
14 / 34

Processos
for)*+

;%erccio" qual a sada do programa a!ai%o<


int main() { int pid, x = 4; pid = fork(); if ( 0 == pid ) { fork(); x=x+2; } else { x--; } printf(x=%d\n,x); }

Italo Valcy Programao em C

15 / 34

P*3(= Threads
.orma internacional (;;; P*3(= 199>-1 C Threads P*3(= podem implementar threads em nvel de usu&rio, em nvel de :ernel ou misto * programa em C deve conter" #include <pthread.h> ; para compilar, / necess&rio incluir a opo -pthread gcc -pthread programa.c

Italo Valcy Programao em C

16 / 34

P*3(= Threads
.-em$lo
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NUM_THREADS 5

void *PrintHello(void *arg) { int *tid = (int *)arg; printf("Hello World! It's me, thread #%d!\n", *tid); pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t threads[NUM_THREADS]; int thread_id[NUM_THREADS]; int rc, t; for(t=0; t<NUM_THREADS; t++){ printf("In main: creating thread %d\n", t); thread_id[t] = t; rc = pthread_create(&threads[t], NULL, PrintHello, (void *)&thread_id[t]); if (rc){ printf("ERROR; return code from pthread_create() is %d\n", rc); exit(-1); } } /* Last thing that main() should do */ pthread_exit(NULL); }

Italo Valcy Programao em C

17 / 34

P*3(= Threads
.-em$lo , $oss/vel sa/da
~$ gcc -pthread -o pthread-hello pthread-hello.c ~$ ./pthread-hello In main: creating thread 0 In main: creating thread 1 Hello World! It's me, thread #0! Hello World! It's me, thread #1! In main: creating thread 2 In main: creating thread 3 Hello World! It's me, thread #2! Hello World! It's me, thread #3! In main: creating thread 4 Hello World! It's me, thread #4!

Italo Valcy Programao em C

18 / 34

;struturas e ,un'es usadas


pthread?t pthread?create() pthread?7oin() pthread?:ill pthread?e%it()

Italo Valcy Programao em C

19 / 34

;struturas e ,un'es usadas


$t#read0t

;strutura de dados para arma enar in,orma'es so!re as threads- Para uso interno do pthread-h
2sada na criao, no 7oin, na ,inali ao, etc

;%emplo"
#include <pthread.h> #define NUM_THREADS 5 pthread_t threads[NUM_THREADS]; ...

Italo Valcy Programao em C

20 / 34

;struturas e ,un'es usadas


$t#read0create*+
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);

Criao de novas threads"


4ocal para salvar as in,orma'es da thread (vetor de pthread?t) Atri!utos da thread (stac: si e, sched method, etc-) 5uno da thread Argumentos (apontador)

@etorna 9 ( ero) se a criao tiver sucessovoid *myfunc(void *arg) { ... return (void *)result; } int main() { pthread_t onethread; int s = pthread_create(&onethread, NULL, &myfunc, NULL); }

Italo Valcy Programao em C

21 / 34

;struturas e ,un'es usadas


$t#read0create*+ , Ar&umentos
pthread_t threads[2]; void *thread_func(void *arg) { int *n = (int *)arg; ... } int main(int argc, char **argv) { int i, a = 10; for(i=0; i<2; i++) { pthread_create(&threads[i], NULL, &thread_func, &a); } ... }

Italo Valcy Programao em C

22 / 34

;struturas e ,un'es usadas


$t#read01oin*+
int pthread_join(pthread_t thread, void *retval);

Aguarda a ,inali ao de uma thread (diretiva de sincroni ao)


A possvel passar um apontador para o!ter retorno da thread

;m sucesso, retorna 9B
... s = pthread_join(onethread, &res); ...

Italo Valcy Programao em C

23 / 34

;struturas e ,un'es usadas


$t#read0e-it*+
void pthread_exit(void *retval);

5inali a uma thread e retorna algum valor atrav/s de retval (pode6se o!t+6lo atrav/s de pthread?7oin)
... pthread_exit(&result); ...

Italo Valcy Programao em C

24 / 34

;%erccio
5a er um programa que rece!e diversos ar&umentos de linha de comando e cria uma thread para imprimir cada argumento na sada padro-

Italo Valcy Programao em C

25 / 34

;%erccio
$t#read-$rint-ar&s.c *2%3+
#include <stdio.h> #include <stdlib.h> #include <pthread.h> typedef struct mythread_args { int id; char *arg_string; } mythread_args_t; void *mythread_handler(void *arg) { mythread_args_t *myarg = (mythread_args_t *)arg; printf("Thread #%d - arg: %s\n", myarg->id, myarg->arg_string); }

Italo Valcy Programao em C

26 / 34

;%erccio
$t#read-$rint-ar&s.c *3%3+
int main(int argc, char **argv) { pthread_t *threads; mythread_args_t *thread_args; int i, s; if (argc <= 1) { printf("%s <ARG1> [<ARG2> ...]\n", argv[0]); } argc--; threads = (pthread_t *)malloc(sizeof(pthread_t)*argc); thread_args = (mythread_args_t *)malloc(sizeof(mythread_args_t)*argc); for(i=0; i < argc; i++) { thread_args[i].id = i; thread_args[i].arg_string = argv[i+1]; printf("MAIN - Criando thread #%d\n", i); s = pthread_create(&threads[i], NULL, &mythread_handler, &thread_args[i]); if (s!=0) { printf(" -> Erro ao criar thread!\n"); exit(1); } } for(i=0; i < argc; i++) { s = pthread_join(threads[i], NULL); if (s!=0) { printf("Error na thread %d!\n", i); exit(1); } } return 0; }

Italo Valcy Programao em C

27 / 34

P*3(= Threads
.-em$lo 3
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NUM_THREADS int saldo = 1000; void *atualizaSaldo(void *arg) { int *tid = (int *)arg; int meu_saldo = saldo; int novo_saldo = meu_saldo + (*tid + 1)*100; printf("Thread #%d - Novo saldo: %d\n", *tid, novo_saldo); saldo = novo_saldo; pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t threads[NUM_THREADS]; int thread_id[NUM_THREADS]; int rc, i; for(i=0; i<NUM_THREADS; i++){ thread_id[i] = i; rc = pthread_create(&threads[i], NULL, &atualizaSaldo, (void *)&thread_id[i]); if (rc) exit(-1); } for(i=0; i < NUM_THREADS; i++) pthread_join(threads[i], NULL); printf("Saldo final: %d\n", saldo); return 0; } 5

Italo Valcy Programao em C

28 / 34

P*3(= Threads
.-em$lo 3 , ordem de e-ecuo

A ordem de e%ecuo no / garantidaC

.ecess&rio" uso de mecanismos de sincroni aoC

Italo Valcy Programao em C

29 / 34

#ecanismos de sincroni ao
;%cluso m0tua
2ma thread est& e%ecutando so inha um determinado c1digo, enquanto as outras esperam para poder e%ecutar

3esso crtica
Parte do programa que deve ser e%ecutada por somente uma thread de cada ve (em e%cluso m0tua)

Italo Valcy Programao em C

30 / 34

#ecanismos de sincroni ao
3em&,oros ) #ute% #onitores Conditions Trocas de mensagem

Italo Valcy Programao em C

31 / 34

#ute%
.-em$lo
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NUM_THREADS 5

int saldo = 1000; pthread_mutex_t saldo_mutex; void *atualizaSaldo(void *arg) { int *tid = (int *)arg; pthread_mutex_lock(&saldo_mutex); int meu_saldo = saldo; int novo_saldo = meu_saldo + (*tid + 1)*100; printf("Thread #%d - Novo saldo: %d\n", *tid, novo_saldo); saldo = novo_saldo; pthread_mutex_unlock(&saldo_mutex); pthread_exit(NULL); } int main (int argc, char *argv[]) { pthread_t threads[NUM_THREADS]; int thread_id[NUM_THREADS]; int rc, i; pthread_mutex_init(&saldo_mutex, NULL); for(i=0; i<NUM_THREADS; i++){ thread_id[i] = i; rc = pthread_create(&threads[i], NULL, &atualizaSaldo, (void *)&thread_id[i]); if (rc) exit(-1); } for(i=0; i < NUM_THREADS; i++) pthread_join(threads[i], NULL); printf("Saldo final: %d\n", saldo); return 0; }

Italo Valcy Programao em C

32 / 34

@e,er+ncia
https"))computing-llnl-gov)tutorials)pthreads)

Italo Valcy Programao em C

33 / 34

;%erccio
#ultiplicao de matri es de ,orma paralela#ultiplicao de matri " A-DEC * calculo de um elemento da #atri C, envolve a multiplicao duma linha de #atri % A com a coluna da #atri D

a b e c d g

f a.e + b.g = h c.e + d .g

a. f + b.h c. f + d .h

.-er(4" 5a er um programa que rece!e duas matri es de tamanho vari&vel (#%P e P%F) como entrada e calcula a multiplicao entre elas em . threads di,erentes (a quantidade de threads tam!/m ser& in,ormada como entrada)
Italo Valcy Programao em C
34 / 34