lecteur / rédacteur verrouillé dans pthread

J’apprends à lire et je suis tombé sur le verrou du lecteur. Le scénario est très simple. une variable globale étant partagée par tous les threads, le lecteur continue à imprimer la valeur actuelle de cette même variable globale, tandis que writer met à jour la même variable. Je peux réaliser cette synchronisation en utilisant deux mutex (pthread_mutex_t), mais je souhaite utiliser le verrou “un” lecteur-écrivain pour obtenir le même résultat. Cependant, avec un verrou lecteur-auteur, comme on peut le voir ici (sortie du programme, ci-dessous), le lecteur ne voit que la première valeur de x et ne voit aucune mise à jour de la variable globale. S’il vous plaît jeter un peu de lumière ici.

Code:

#include  #include  #include  #include  #include  #define ACCESS_ONCE(x) (*(volatile typeof(x) *)&(x)) int x = 0; pthread_rwlock_t lock_rw = PTHREAD_RWLOCK_INITIALIZER; void *reader_thread(void *arg) { int i; int newx, oldx; newx = oldx = -1; pthread_rwlock_t *p = (pthread_rwlock_t *)arg; if (pthread_rwlock_rdlock(p) != 0) { perror("reader_thread: pthread_rwlock_rdlock error"); exit(__LINE__); } for (i = 0; i < 100; i++) { newx = ACCESS_ONCE(x); if (newx != oldx) { printf("reader_lock: x: %d\n",x); } oldx = newx; poll(NULL, 0, 1); } if (pthread_rwlock_unlock(p) != 0) { perror("reader thread: pthred_rwlock_unlock error"); exit(__LINE__); } return NULL; } void *writer_thread(void *arg) { int i; pthread_rwlock_t *p = (pthread_rwlock_t *)arg; if (pthread_rwlock_wrlock(p) != 0) { perror("writer thread: pthread_rwlock_wrlock error"); exit(__LINE__); } for (i = 0; i < 3; i++) { ACCESS_ONCE(x)++; poll(NULL, 0, 5); } if (pthread_rwlock_unlock(p) != 0) { perror("writer thread: pthread_rwlock_unlock error"); exit(__LINE__); } return NULL; } int main(void) { pthread_t tid1, tid2; void *vp; if (pthread_create(&tid1, NULL, reader_thread, &lock_rw) != 0) { perror("pthread_create error"); exit (__LINE__); } if (pthread_create(&tid2, NULL, writer_thread, &lock_rw) != 0) { perror("pthread_create error"); exit (__LINE__); } //wait for the thread to complete if (pthread_join(tid1, &vp) != 0) { perror("pthread_join error"); exit (__LINE__); } if (pthread_join(tid2, &vp) != 0) { perror("pthread_join error"); exit (__LINE__); } printf("Parent process sees x: %d\n",x); return 0; } 

gcc pthread_rwlock.c -o rwlock -pthread -Wall -Werror

./rwlock

reader_lock: x: 0

Le processus parent voit x: 3

Lorsqu’un thread acquiert un verrou, les autres threads essayant d’acquérir le même verrou seront suspendus jusqu’à ce que le premier thread libère le verrou.

Ce qui se passe ici, c’est que votre thread de lecteur démarre, acquiert le verrou et entre dans la boucle for/poll .

Le fil d’écriture démarre, tente d’acquérir le verrou déjà pris par le fil de lecture et rest bloqué sur pthread_rwlock_wrlock .

Ce que vous voulez réellement faire est de placer votre lock/unlock juste avant et après le code où vous accédez à votre variable partagée.

 thread_rwlock_rdlock(p); newx = ACCESS_ONCE(x); thread_rwlock_unlock(p); ... thread_rwlock_wrlock(p); ACCESS_ONCE(x)++; thread_rwlock_unlock(p);