Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
● 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