linguagem de programação iwiki.cbatista.net/lib/exe/fetch.php/lpi-aula16-threads-b.pdf · quando...

Post on 12-Aug-2020

1 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Linguagem de Programação I

Carlos Eduardo Batista !

Centro de Informática - UFPB bidu@ci.ufpb.br

● Exemplo: ◦ Explorar Templates e Exceções ◦ Incrementar com o uso de STL

"2

Exercícios

● Crie uma função verificarPalindromo() que recebe um vetor como parâmetro. Ela deve retornar true se ele contém um palíndromo e false caso contrário. ◦ Exemplo: Um vetor contendo 1, 2, 3, 2, 1 é um palíndromo. E

um vetor contendo 1, 4, 3, 2, 1 não é um palíndromo. !

● Crie uma mapa que associa o nome de uma pessoa a um objeto do tipo Pessoa. A classe Pessoa deve ser feita usando templates, armazenando uma variável de tipo arbitrário. Crie um programa que leia entradas e armazene utilizando a classe map. Caso o usuário tente cadastrar uma chave duplicada, uma exceção deve ser lançada.

"3

Processo x thread

● Processo - Um conjunto de recursos necessários para a execução duma programa. ◦ um espaço de endereçamento (virtual address space) que contêm o texto do programa e os seus dados ◦ uma tabela de descritores de arquivos abertos ◦ informação sobre processos filhos ◦ código para tratar sinais (signal handlers) ◦ informação sobre o próprio etc.

"4

Processo x thread

● Uma linha ou contexto de execução, chamada “Thread” ◦ Uma thread tem um programa counter (pc) que guarde informação sobre a próxima instrução a executar ◦ Registadores – valores das variáveis atuais ◦ Stack – contem a história de execução com um “frame” para cada procedimento chamado mas não terminado

"5

Criação de processos

O processo filho é uma cópia exata do processo que chama a rotina fork(), sendo a única diferença um identificador de processo (pid) diferente

pid = fork() if (pid == 0) código executado pelo filho else código executado pelo pai if (pid == 0) exit (0); else wait (0); //esperar pelo filho .. JOIN

Programa principal

FORK

JOIN

FORK

FORK

JOIN JOIN JOIN

Spawned processes

paifilho e pai do

Inter Process Communication –

Pipes, Shared Memory, Signal etc.

realidade

conceito

context switch

O modelo de threads

● Os dois conceitos necessários para a execução dum programa, “conjunto de recursos” e “contexto de execução” podem ser separados:

● Processos são usados para agrupar recursos.

● Threads são as entidades escalonadas para execução no CPU.

"8

Processos versus Threads

Arquivos

IP

CódigoHeap

Rotinas de interrupção

Heavyweight Process: programas completamente separados com suas próprias variáveis, pilha e alocação de memória

Arquivos

IPCódigo

Heap

Rotinas de interrupçãoIP

Threads: lightweight processes rotinas compartilham o mesmo espaço de memória e variáveis globais

stack

stack

stack

Processos versus Threads

• Program Counter • Address Space

• Stack • Global Variables • Register Set • Open Files

• Child Threads • Child Processes

• State (ready,blocked ..) !

• Timers

• Signals

• Semaphores

• Accounting Information

Per Thread Items Per Process Items

realidade

conceito

context switch

0

high

codigo biblioteca

dados

registers

CPU

R0

Rn

PC

“memoria”

x

x

Text programacommon runtime

stack

address space

SPy

y stack

Thread Em execução

Thread pronto para executar

Environ $USER=A1

Threads x processos

● A criação e terminação duma thread nova é em geral mais rápida do que a criação e terminação dum processo novo.

● A comutação de contexto entre duas threads é mais rápido do que entre dois processos.

● A comunicação entre threads é mais rápida do que a comunicação entre processos - porque as threads compartilham tudo: espaço de endereçamento, variáveis globais etc.

● Multi-programação usando o modelo de threads é mais simples e mais portável do que multi-programação usando múltiplos processos.

"12

Implementação

● Existem duas abordagens principais para a implementação de threads.

● Kernel-level Threads -- System Calls. ● User-Level Threads -- Thread Libraries. ● Existem vantagens e desvantagens em

ambos os casos.

"13

Kernel threads

● Vantagens ◦ O kernel pode simultaneamente escalonar várias threads do mesmo processo em vários processadores (reais ou virtuais) ◦ As rotinas do próprio kernel podem aproveitar threads.

● Desvantagens: ◦ A troca entre threads implica ações do kernel e isto tem um custo que pode ser significativo.

"14

User level threads

● Vantagens ◦ A troca de Threads não envolve o kernel ◦ Não há o custo adicional de execução do kernel ◦ O OS não precisa de oferecer apoio para threads – portanto é mais simples. ◦ Escalonamento pode ser especifico para uma aplicação ◦ Uma biblioteca pode oferecer vários métodos de escalonamento portanto uma

aplicação poderá escolher o algoritmo melhor para ele. ◦ ULTs podem executar em qualquer SO ◦ As bibliotecas de código são portáveis

● Desvantagens ◦ Muitas das chamadas ao sistema são “bloqueantes” e o kernel bloqueia

processos – neste caso todos as threads dum processo podem ser bloqueados.

◦ O kernel vai atribuir o processo a apenas um CPU portanto duas threads dentro do mesmo processo não podem executar simultaneamente numa arquitetura com múltiplas processadores

"15

Pthreads

● POSIX 1003.1-2001 – pthreads ● API para gerenciamento de threads ◦ >more /usr/include/pthread.h ◦ > man pthread_create

● Threads co-existem num mesmo processo, compartilhando vários recursos, mas são escalonadas separadamente pelo sistema operacional

● Somente o mínimo necessário de recursos é replicado entre duas threads

"16

Visão geral

Sem Threads Com Threads

Pthreads

Interface portável do sistema operacional, POSIX, IEEE

Programa principal

pthread_create( &thread1, NULL, proc1, &arg);

pthread_join( thread1, NULL ou *status);

thread1

proc1(&arg); {

return(&status); }

Código da thread

PThread APIPrefix Funcionality

pthread_ Threads themselves and miscellaneous subroutines

pthread_attr_ Thread attributes objects

pthread_mutex_ Mutexes

pthread_mutexattr_ Mutex attributes objects

pthread_cond_ Condition variables

pthread_cond_attr Condition attributes objects

pthread_key_ Thread-specific data keys

Como programar

● Usar ◦ #include “pthread.h”

● Compilar com a opção –pthread ◦ gcc –pthread ex_pthread.c –o ex_pthread

Criando uma thread

int pthread_create(pthread_t * thread, const pthread_attr_t * attr, void * (*start_routine)(void *), void *arg);

pthread_create

#include <stdio.h> #include <stdlib.h> #include <pthread.h> void *print_message_function( void *ptr ); main() { pthread_t thread1, thread2; char *message1 = "Thread 1“, *message2 = "Thread 2"; int iret1, iret2; iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1); iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2); pthread_join( thread1, NULL); pthread_join( thread2, NULL); printf("Thread 1 returns: %d\n",iret1); printf("Thread 2 returns: %d\n",iret2); exit(0); } void *print_message_function( void *ptr ) {

char *message; message = (char *) ptr;

printf("%s \n", message); }

Encerrando uma thread

● Além da alternativa de simplesmente encerrar a função, é possível também ◦ void pthread_exit(void *retval);

Pthread Join

● A rotina pthread_join() espera pelo término de uma thread específica !for (i = 0; i < n; i++) pthread_create(&thread[i], NULL, (void *) slave,

(void *) &arg); !...thread mestre !for (i = 0; i < n; i++) pthread_join(thread[i], NULL);

Detached Threads (desunidas)

Pode ser que uma thread não precisa saber do término de uma outra por ela criada, então não executará a operação de união. Neste caso diz-se que o thread criado é detached (desunido da thread pai progenitor)

Programa principal

pthread_create();

pthread_create();

Thread

pthread_create();Thread

Thread Término

TérminoTérmino pthread_exit

Pthreads

● Quando dois ou mais threads podem simultaneamente alterar às mesmas variaveis globais poderá ser necessário sincronizar o acesso a este variavel para evitar problemas.

● Código nestas condição diz-se “uma seção critica” ◦ Por exemplo, quando dois ou mais threads podem

simultaneamente incrementar uma variável x ◦ /* codigo – Seção Critica */ ◦ x = x +1 ;

● Uma seção crítica pode ser protegida utilizando-se pthread_mutex_lock() e pthread_mutex_unlock()

"26

Mutex

/* Note scope of variable and mutex are the same */ pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; int counter=0; !/* Function C */ void functionC() { pthread_mutex_lock( &mutex1 ); counter++ pthread_mutex_unlock( &mutex1 ); }

Fontes de problemas

● Condição de corrida ◦ Não assuma uma ordem específica para a execução das threads ◦ Um código pode funcionar muito bem em determinados momentos e gerar sérios problemas em outros

● Thread safe code ◦ Use bibliotecas que possuam chamadas “thread safe” ◦ Várias chamadas à mesma função devem ser permitidas

● Deadlock

Threads STD (C++11)

● Biblioteca padrão STD passou a incluir suporte a threads

● Criação e gerência do ciclo de vida de threads

● #include <thread> ● Compilador deve suportar C++11 ◦ Opções -std=c++0x" ou "-std=c++11" no G++ para ativar suporte

Threads STD (C++11)

#include <iostream> // std::cout #include <thread> // std::thread !void foo() { std::cout << “foo!” << endl; } !void bar(int x) {std::cout << “bar: ” << x << endl; } !int main() { std::thread first (foo); // spawn new thread that calls foo() std::thread second (bar,10); // spawn new thread that calls bar(10) ! std::cout << "main, foo and bar now execute concurrently...\n"; ! // synchronize threads: first.join(); // pauses until first finishes second.join(); // pauses until second finishes ! std::cout << "foo and bar completed.\n"; ! return 0; }

Threads STD (C++11)

class thread { public: class id; typedef /*implementation-defined*/ native_handle_type; ! thread() noexcept; template <class F, class ...Args> explicit thread(F&& f, Args&&... args); ~thread(); thread(const thread&) = delete; thread(thread&&) noexcept; thread& operator=(const thread&) = delete; thread& operator=(thread&&) noexcept; void swap(thread&) noexcept; bool joinable() const noexcept; void join(); void detach(); id get_id() const noexcept; native_handle_type native_handle(); static unsigned hardware_concurrency() noexcept; };

Threads STD (C++11)

this_thread provide functions that access current the thread of execution

yield!(C++11)

suggests that the implementation reschedule execution of threads (function)

get_id!(C++11)

returns the thread id of the current thread (function)

sleep_for!(C++11)

stops the execution of the current thread for a specified time duration (function)

sleep_until!(C++11)

stops the execution of the current thread until a specified time point (function)

Threads STD (C++11)

#include <thread> #include <iostream> #include <vector> !void hello(){ std::cout << "Hello from thread “; std::cout << std::this_thread::get_id() << std::endl; } !int main(){ std::vector<std::thread> threads; for(int i = 0; i < 5; ++i){ threads.push_back(std::thread(hello)); } for(auto& thread : threads){ thread.join(); } return 0; }

Threads STD (C++11)

#include <thread> #include <iostream> class TestClass { int i; public: TestClass(int n) { i = n; } void greeting(std::string const& message) const { std::cout << message << std::endl; std::cout << "My number: " << n << std::endl; } }; int main() { TestClass x(10); std::thread t(& TestClass::greeting,&x,"Hello! "); t.join(); }

Threads STD (C++11)

#include ... !int main() { std::shared_ptr<SayHello> p(new SayHello); std::thread t(&SayHello::greeting,p,"goodbye"); t.join(); } !// What if you want to pass in a reference to an // existing object, and a pointer just won't do? // That is the task of std::ref.

Threads STD (C++11)

#include <thread> #include <iostream> !void write_sum(int x,int y) { std::cout<<x<<" + "<<y<<" = "<<(x+y)<<std::endl; } !int main() { std::thread t(write_sum,123,456); t.join(); }

Threads STD (C++11)

#include <thread> #include <iostream> #include <functional> // for std::ref class PrintThis { public: void operator()() const { std::cout<<"this="<<this<<std::endl; } }; int main() { PrintThis x; x(); std::thread t(std::ref(x)); t.join(); std::thread t2(x); t2.join(); }

/* this=0x7fffb08bf7ef this=0x7fffb08bf7ef this=0x42674098 */

Threads STD (C++11)

#include <thread> #include <iostream> #include <functional> !void increment(int& i) { ++i; } !int main() { int x=42; std::thread t(increment,std::ref(x)); t.join(); std::cout<<"x="<<x<<std::endl; }

Threads STD (C++11)

● Leitura complementar ● http://cppwisdom.quora.com/Why-

threads-and-fork-dont-mix ● http://www.linuxprogrammingblog.com/

threads-and-fork-think-twice-before-using-them

Referências

● Notas de aula – Claudio Esperança e Paulo Cavalcanti (UFRJ)

● Notas de aula – Allan Lima (citi/UFPE)

"40

Linguagem de Programação I

Carlos Eduardo Batista !

Centro de Informática - UFPB bidu@ci.ufpb.br

top related