/* * Implementação com alto paralelismo, mas sujeita a starvation. * * Transformação simplista para locks e variáveis de condição. * Por que não funciona? */ #include #include #include #include #define N 5 #define MAX_REFEICOES 100 #define ESQ (phil_id + 1) % N #define DIR (phil_id + N - 1) % N typedef enum {T, H, E} estado_t; estado_t estado[N]; pthread_mutex_t mutex; pthread_cond_t filosofo[N]; /* Contabilidade */ pthread_mutex_t mutex_ref; int refeicoes[N], total_refeicoes; /* Considera que já adquiriu o mutex ou está no início da execução */ void exibe_mesa() { int i; for (i = 0; i < N; i++) switch (estado[i]) { case T: printf("T "); break; case H: printf("H "); break; case E: printf("E "); break; } printf("\n"); } /* Considera que já adquiriu o mutex */ void testa_garfos(int phil_id) { if (estado[phil_id] == H && estado[ESQ] != E && estado[DIR] != E) { estado[phil_id] = E; exibe_mesa(); pthread_cond_signal(&filosofo[phil_id]); } } void pensa(int phil_id) { sleep(1); } void pega_garfos(int phil_id) { pthread_mutex_lock(&mutex); estado[phil_id] = H; exibe_mesa(); testa_garfos(phil_id); pthread_mutex_unlock(&mutex); pthread_cond_wait(&filosofo[phil_id], &mutex); } void come(int phil_id) { pthread_mutex_lock(&mutex_ref); refeicoes[phil_id]++; total_refeicoes++; if (total_refeicoes == MAX_REFEICOES) { int i; printf("Total de refeicoes: \n"); for (i = 0; i < N; i++) printf("Filosofo %d: %d\n", i, refeicoes[i]); /* Aborta execução */ exit(0); } pthread_mutex_unlock(&mutex_ref); sleep(1); } void solta_garfos(int phil_id) { pthread_mutex_lock(&mutex); estado[phil_id] = T; exibe_mesa(); testa_garfos(ESQ); testa_garfos(DIR); pthread_mutex_unlock(&mutex); } void* f_phil(void *v) { int phil_id = *(int *) v; while(1) { pensa(phil_id); pega_garfos(phil_id); come(phil_id); solta_garfos(phil_id); } } int main() { pthread_t thr[N]; int i, phil_id[N]; pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex_ref, NULL); total_refeicoes = 0; for (i = 0; i < N; i++) { phil_id[i] = i; pthread_cond_init(&filosofo[i], NULL); estado[i] = T; refeicoes[i] = 0; } exibe_mesa(); for (i = 0; i < N; i++) pthread_create(&thr[i], NULL, f_phil, (void*) &phil_id[i]); for (i = 0; i < N; i++) pthread_join(thr[i], NULL); return 0; }