#include #include #include #include pthread_mutex_t lock; /* Mutexes robustos lidam com o caso em que a thread/processo que possui o lock morre/termina abruptamente, sem antes liberar o lock. Isto possivelmente impediria todas as outras threads de obterem o lock novamente, mas lock robustos podem ser recuperados. Quando uma thread que possuia o lock morre, uma das threads que esperava pelo mutex o consegue, recebendo como retorno o erro EOWNERDEAD. Esta thread precisa então verificar o estado da aplicação e corrigi-lo, já que a thread que morreu foi interrompida sem finalizar a região crítica, o que pode ter deixado a aplicação em um estado inconsistente. Após esta possível correção, a thread que obteve o lock deve invocar a função pthread_mutex_consistent_np, sinalizando que o mutex agora está novamente consistente e pode ser usado como antes. Esta thread pode então executar sua RC e continuar o fluxo da aplicação. */ void* f_thread1(void *v) { pthread_mutex_lock(&lock); printf("Thr1 - Lock obtido.\n"); sleep(5); /* A Thread morre sem liberar o lock. */ printf("Thr1 - Suicídio!\n"); pthread_exit(0); return NULL; } void* f_thread2(void *v) { /* Sleep para garantir que a thread1 obtenha o lock. */ sleep(1); /* Verifica se o retorno é EOWNERDEAD. Neste caso, é responsabilidade desta thread corrigir o estado da aplicação e invocar pthread_mutex_consistent_np para tornar o mutex novamente consistente. */ if (pthread_mutex_lock(&lock) == EOWNERDEAD) { printf("Thr2 - Thread que mantinha o lock morreu.\n"); printf("Thr2 - Tornando o lock consistente.\n"); pthread_mutex_consistent_np(&lock); } else { printf("Thr2 - Obtendo o lock normalmente.\n"); } printf("Thr2 - Executando região crítica.\n"); pthread_mutex_unlock(&lock); return NULL; } void* f_thread3(void *v) { sleep(1); /* A Thread 3 possui o mesmo código que a Thread 2, simulando concorrência pelo lock e demonstrando que qualquer que uma das threads pode receber EOWNERDEAD. */ if (pthread_mutex_lock(&lock) == EOWNERDEAD) { printf("Thr3 - Thread que mantinha o lock morreu.\n"); printf("Thr3 - Tornando o lock consistente.\n"); pthread_mutex_consistent_np(&lock); } else { printf("Thr3 - Obtendo o lock normalmente.\n"); } printf("Thr3 - Executando região crítica.\n"); pthread_mutex_unlock(&lock); return NULL; } int main() { pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP); pthread_mutex_init(&lock, &attr); pthread_t thr1, thr2, thr3; pthread_create(&thr1, NULL, f_thread1, NULL); pthread_create(&thr2, NULL, f_thread2, NULL); pthread_create(&thr3, NULL, f_thread3, NULL); pthread_join(thr1, NULL); pthread_join(thr2, NULL); pthread_join(thr3, NULL); printf("Finalizando programa.\n"); return 0; }