/* * Leitores e escritores utilizando locks e variáveis * de condição. * Possibilidade de leitores simultâneos, mas * também de starvation dos escritores. */ #include #include #include #include #include #define NL 10 #define NE 3 volatile int bd = -1; /* Banco de dados */ volatile int nl = 0; volatile int ne = 0; /* Para execução sem verificação de erros */ pthread_mutex_t lock_bd = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t lock_cont = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t cond_bd; void *leitor(void* v) { int id = *(int*) v; pthread_mutex_lock(&lock_cont); while (ne > 0) pthread_cond_wait(&cond_bd, &lock_cont); nl++; pthread_mutex_unlock(&lock_cont); sleep(1); printf("Leitor %d leu o valor %d \n", id, bd); pthread_mutex_lock(&lock_cont); nl--; if (nl == 0) pthread_cond_signal(&cond_bd); pthread_mutex_unlock(&lock_cont); return NULL; } void *escritor(void *v) { int id = *(int*) v; pthread_mutex_lock(&lock_cont); while (nl > 0 || ne > 0) pthread_cond_wait(&cond_bd, &lock_cont); ne++; pthread_mutex_unlock(&lock_cont); bd = id; sleep(2); printf("Escritor %d escreveu o valor %d \n", id, bd); pthread_mutex_lock(&lock_cont); ne--; pthread_cond_broadcast(&cond_bd); pthread_mutex_unlock(&lock_cont); return NULL; } void *gera_leitores(void *v) { pthread_t thr_l[NL]; int l_id[NL]; int i; for (i = 0; i < NL ; i++) { l_id[i] = i; pthread_create(&thr_l[i], NULL, leitor, &l_id[i]); sleep(random() % 3); } for (i = 0; i < NL; i++) pthread_join(thr_l[i], NULL); return NULL; } void *gera_escritores(void *v) { pthread_t thr_e[NE]; int e_id[NE]; int i; for (i = 0; i < NE; i++) { e_id[i] = i; pthread_create(&thr_e[i], NULL, escritor, &e_id[i]); sleep(random() % 3); } for (i = 0; i < NE; i++) pthread_join(thr_e[i], NULL); return NULL; } int main() { pthread_t thr_gera_esc, thr_gera_leit; pthread_create(&thr_gera_leit, NULL, gera_leitores, NULL); pthread_create(&thr_gera_esc, NULL, gera_escritores, NULL); pthread_join(thr_gera_leit, NULL); pthread_join(thr_gera_esc, NULL); return 0; }