2010-08-24 6 views
0

J'ai écrit ma propre version de la file d'attente sûre. Cependant, lorsque je lance ce programme, il se bloque/se bloque lui-même. Vous vous demandez pourquoi cela est bloqué pour toujours. J'ai écrit le casier de classe RAII.Pourquoi cette file d'attente sûre, crée un blocage?

class locker 
{ 
public: 
    locker(pthread_mutex_t& lockee): target(lockee) 
    { 
     pthread_mutex_lock(&target); 
    } 
    ~locker() 
    { 
     pthread_mutex_unlock(&target); 
    } 
private: 
     pthread_mutex_t target; 
}; 

Mon code de thread d'auteur/lecteur est très simple. Le thread d'écriture, ajouté à la file d'attente et au thread de lecture, lit dans la file d'attente.

void * writeintoqueue(void* myqueue) 
{ 
    void *t = 0; 
    concurrentqueue *localqueue = (concurrentqueue *) myqueue; 

    for (int i = 0; i < 10 ; ++i) 
    { 
     localqueue->addtoQueue(i*10); 
    } 

    pthread_exit(t); 
} 

void * readfromqueue(void* myqueue) 
{ 
    void *t = 0; 
    concurrentqueue *localqueue = (concurrentqueue *) myqueue; 
    int number = 0; 
    for (int i = 0 ; i < 10 ; ++i) 
    { 
     number = localqueue->getFromQueue(); 
     std::cout << "The number from the queue is " << number << std::endl; 
    } 
    pthread_exit(t); 
} 
+9

Je ne suis pas un expert en pthreads, mais je ne pense pas que vous vouliez copier votre 'pthread_mutex_t' par valeur dans' target' dans votre classe 'locker'. Faites 'target' un' pthread_mutex_t & 'ou' pthread_mutex_t * '. – msandiford

+3

@spong Je suis certain que c'est le problème. En faisant une copie, le verrouillage et la signalisation ne traitent plus avec la même structure, ce qui entraînerait la perte de beaucoup d'implémentations pthread. Vous devriez ajouter votre commentaire en guise de réponse. –

+0

Pourquoi réinventer la roue. C'est la mise en œuvre que j'utilise. http://gist.github.com/482342 –

Répondre

2

Reformuler commentaire de spong comme une réponse: votre classe locker ne devrait pas être la copie pthread_mutex_t par valeur. Vous devez utiliser une référence ou un pointeur au lieu, par exemple:

class locker 
{ 
public: 
    locker(pthread_mutex_t& lockee): target(lockee) 
    { 
     pthread_mutex_lock(&target); 
    } 
    ~locker() 
    { 
     pthread_mutex_unlock(&target); 
    } 
private: 
     pthread_mutex_t& target; // <-- this is a reference 
}; 

La raison en est que tous les types de données pthreads doivent être traités comme des types opaques - vous ne savez pas ce qui est en eux et ne doit pas les copier . La bibliothèque fait des choses comme regarder une adresse mémoire particulière pour déterminer si un verrou est maintenu, donc s'il y a deux copies d'une variable qui indique si le verrou est maintenu, des choses étranges peuvent se produire, comme plusieurs threads semblant réussir à verrouiller le même mutex.

J'ai testé votre code, et il est également dans l'impasse pour moi. Je l'ai ensuite passé à travers Valgrind, et bien qu'il ne se soit pas bloqué dans ce cas (en raison de temporisations différentes, ou peut-être que Valgrind ne simule qu'un thread à la fois), Valgrind a signalé de nombreuses erreurs. Après avoir corrigé locker pour utiliser une référence à la place, il a fonctionné sans super-verrouillage et sans générer d'erreur dans Valgrind. Voir aussi Debugging with pthreads

+0

Merci Adam. Appréciez votre réponse. – user373215

5

Ceci est certainement pas sûr:

if (empty()) 
{ 
    pthread_cond_wait(&queue_availability_condition,&lock_for_queue); 
} 

Si un autre thread qui n'a pas été précédemment appels getFromQueue() après avoir attendu addtoQueue() a signalé la variable d'état et est sorti, mais avant que le fil d'attente a aquired la serrure, cette Le thread peut sortir et attendre que la file d'attente ait des valeurs. Vous devez vérifier que la file d'attente n'est pas vide.

Changez le cas dans un certain temps:

while (empty()) 
{ 
    pthread_cond_wait(&queue_availability_condition,&lock_for_queue); 
} 
+0

Est-ce la cause des blocages? – user373215

+0

@nsivakr, cela peut être la cause de nombreux problèmes, dans votre cas appelant front() sur une liste vide, mais ce n'est pas la cause de votre blocage je ne pense pas. Je crois que Spong a le droit. –

Questions connexes