-
Variáveis Globais:
shared_data
: dado compartilhado entre os threads.reader_count
: contador de leitores ativos.lock
ewrite_lock
: mutexes para sincronizar o acesso aos dados e evitar conflitos.
-
Função
reader
(Leitor):- Cada leitor incrementa
reader_count
comlock
. - O primeiro leitor bloqueia
write_lock
, impedindo escritores de acessar o dado enquanto leitores estiverem lendo. - Ao finalizar, o leitor decrementa
reader_count
. Se for o último, liberawrite_lock
.
- Cada leitor incrementa
-
Função
writer
(Escritor):- O escritor adquire
write_lock
antes de alterarshared_data
e o libera após a modificação, garantindo acesso exclusivo ao dado.
- O escritor adquire
-
Execução no
main
:- Inicializa os mutexes.
- Cria cinco threads leitores e dois escritores, executando-os simultaneamente.
- Espera todos terminarem e, por fim, destrói os mutexes.
Essa estrutura permite leituras simultâneas e exclusividade para escrita, evitando conflitos e mantendo a integridade de shared_data
.
-
Variáveis Globais:
ready
: indica se o sinal está pronto para ser recebido.lock
: mutex que controla o acesso à variávelready
.cond
: condição usada para notificar o thread que está esperando.
-
Função
waiter
(Esperador):- Esse thread trava
lock
e verificaready
. - Caso
ready
seja 0, ele entra em espera usandopthread_cond_wait
, liberandolock
e pausando até quecond
seja sinalizado. - Quando recebe o sinal, ele prossegue e libera
lock
.
- Esse thread trava
-
Função
sender
(Enviador):- Esse thread trava
lock
, defineready
como 1 e sinaliza a condiçãocond
. - Isso acorda o thread em espera (
waiter
), que pode então continuar sua execução. - Após sinalizar, ele libera
lock
.
- Esse thread trava
-
Execução no
main
:- Inicializa o mutex e a condição.
- Cria o thread
waiter
(esperador) e o threadsender
(enviador). - Aguarda ambos terminarem com
pthread_join
. - Por fim, destrói o mutex e a condição.
Esse código mostra a sincronização entre threads usando uma condição: o waiter
espera um sinal para continuar, que é enviado pelo sender
ao definir ready = 1
.
-
Mutexes:
lock1
elock2
são dois mutexes que representam recursos que os threads precisam adquirir em uma ordem específica.
-
Função
thread1
:thread1
adquirelock1
e imprime uma mensagem.- Após um
sleep
, ele tenta adquirirlock2
. - Quando
thread1
tem ambos os mutexes, ele os libera na ordem inversa.
-
Função
thread2
:thread2
adquirelock2
primeiro e imprime uma mensagem.- Após um
sleep
, ele tenta adquirirlock1
. - Assim como
thread1
, ele libera os mutexes na ordem inversa quando ambos estão adquiridos.
-
Execução no
main
:- Inicializa os mutexes e cria os dois threads (
t1
et2
). - Aguarda que ambos terminem com
pthread_join
. - Finalmente, destrói os mutexes.
- Inicializa os mutexes e cria os dois threads (
O deadlock ocorre porque thread1
e thread2
esperam indefinidamente um pelo outro: thread1
segura lock1
enquanto espera lock2
, e thread2
segura lock2
enquanto espera lock1
. Isso simula uma situação de impasse, onde nenhum thread pode avançar.
-
Barreira:
- A barreira (
pthread_barrier_t barrier
) é configurada para permitir a passagem quando todas asNUM_THREADS
threads atingirem o ponto de espera.
- A barreira (
-
Função
thread_func
:- Cada thread imprime uma mensagem ao chegar na barreira e, em seguida, chama
pthread_barrier_wait
, aguardando que todas as outras threads também alcancem esse ponto. - Após todas as threads chegarem à barreira, elas continuam a execução e imprimem uma mensagem informando que passaram pela barreira.
- Cada thread imprime uma mensagem ao chegar na barreira e, em seguida, chama
-
Execução no
main
:- Inicializa a barreira com o número total de threads (
NUM_THREADS
). - Cria as threads, passando um identificador único (
thread_ids[i]
) para cada uma. - Usa
pthread_join
para esperar a conclusão de todas as threads. - Destrói a barreira após o término das threads.
- Inicializa a barreira com o número total de threads (
Esse código sincroniza os threads usando uma barreira, garantindo que todas cheguem a um ponto comum antes de prosseguir, o que é útil para coordenar tarefas em fases.