verrou de lecture/écriture dans pthread
Je suis en train d'apprendre pthread et suis tombé sur un verrou en lecture /écriture. Le scénario est très simple, une variable globale partagée par tous les threads, le lecteur garde l'impression de la valeur actuelle de cette même variable globale, tandis que l'écrivain sera mise à jour de la même variable. Je peux réaliser cette synchronisation à l'aide de deux mutex (pthread_mutex_t), mais je veux utiliser "un" lecteur-écrivain de verrouillage pour parvenir à ce même résultat. Cependant, avec un lecteur-écrivain de verrouillage, 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 toutes les mises à jour de la variable globale. S'il vous plaît jeter un peu de lumière ici.
Code:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include <poll.h>
#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
Processus Parent voit x: 3
Pourquoi sont deux mutex nécessaires pour obtenir une synchronisation? Ai-je raté quelque chose?
OriginalL'auteur Amit | 2013-10-20
Vous devez vous connecter pour publier un commentaire.
Lorsqu'un thread acquiert un verrou, d'autres threads tentent d'acquérir la même serrure sera suspendu jusqu'à ce que le premier thread libère le verrou.
Ce qui se passe ici est que votre lecteur de fil démarre, acquiert le château, et entre dans la
for/poll
boucle.L'écrivain thread démarre, essaie d'acquérir le verrou qui a été déjà prises par le thread de lecture, et reste bloqué sur
pthread_rwlock_wrlock
.Ce que vous voulez faire est de mettre votre
lock/unlock
juste avant et après le code où vous accédez à votre variable partagée.rwlock n'introduit pas d'supplémentaire de garanties de sécurité sur la norme de mutex. Cependant, il peut réduire le problème de lecteur haute contention (mais pas nécessairement, car il est plus compliqué et de verrouillage, il est plus lent).
De l'homme pages de pthread_rwlock_wrlock, "Le thread appelant acquiert le verrou d'écriture si aucun autre thread (de lecture ou d'écriture) détient le verrou en lecture / écriture rwlock. Sinon, le thread est bloc jusqu'à ce qu'il peut acquérir le verrou". J'étais donc en supposant que l'écrivain ne sera pas bloqué, mais ce n'est pas le cas. Je suppose que j'ai besoin d'explorer plus sur le lecteur-écrivain serrures afin de comprendre pleinement les cas d'utilisation. Merci @zch. Pour l'instant, je vais vivre avec ce que Flavio a suggéré.
@Zch dit, lire/écrire les verrous de faire une différence que si vous avez beaucoup de lecteur de threads accèdent à la même valeurs. Si vous avez un seul lecteur, lire/écrire les verrous se comportent de la même façon standard les mutex.
Le but de la lecture écrivain écluses est de permettre à de nombreux lecteurs de tenir le verrou en lecture simultanément, mais encore donner un accès exclusif à des écrivains. Avec un simple mutex, tous les threads ont un accès exclusif.
OriginalL'auteur Flavio