2017-01-04 4 views
1

J'ai une application avec 2 qthreads qui se comportent comme dans le pseudo-code ci-dessous (les sémaphores sont de type QSemaphore):Mutex échec de déverrouillage lors d'une tentative d'acquérir un QSemaphore

Thread1 { 
    print("about to wait on semaphore 1"); 
    sem1.acquire(1); 
    print("finished waiting on semaphore 1"); 
    sem2.release(1); 
} 

Thread2 { 
    print("signaling semaphore 1"); 
    sem1.release(1); 
    print("about to wait on semaphore 2"); 
    sem2.acquire(1); 
} 

Le problème est que le premier fil ne se réveille pas lorsque le premier sémaphores est signalé, à savoir l'application produit la sortie suivante:

about to wait on semaphore 1 
signaling semaphore 1 
about to wait on semaphore 2 

Et voilà. Le premier fil ne se réveille plus.

Maintenant, je change le premier fil pour effectuer les opérations suivantes:

Thread1 { 
    print("about to wait on semaphore 1"); 
    while (!sem1.tryAcquire(1, 200)); 
    print("finished waiting on semaphore 1"); 
    sem2.release(1); 
} 

Dans ce cas, le premier fil dort dans la plupart 200ms avant d'essayer d'acquérir à nouveau la sémaphores. Maintenant, je reçois l'erreur suivante:

QWaitCondition::wait(): mutex unlock failure: Invalid argument 

Aucun autre mutex ou d'autres primitives de synchronisation sont utilisés par l'application. Quel pourrait être le problème?

Mise à jour:

J'ai enlevé les sémaphores et remplacé chacun avec un QWaitCondition et un QMutex et maintenant il fonctionne très bien. Je n'ai pas fait d'autres changements et je ne sais toujours pas pourquoi la version avec des sémaphores était incorrecte. Ils ont tous deux été initialisés à 0.

Répondre

0

Probablement que vous faites quelque chose de mal quelque part ailleurs (par exemple, le code d'initialisation de sémaphore).


L'exemple suivant est compilé et exécuté (gcc).

threads.h:

#pragma once 

#include <QThread> 

class Thread1 : public QThread 
{ 
protected: 
    virtual void run(); 
}; 

class Thread2 : public QThread 
{ 
protected: 
    virtual void run(); 
}; 

threads.cpp:

#include "threads.h" 

#include <QSemaphore> 
#include <iostream> 

namespace 
{ 
QSemaphore sem1, sem2; 
} 

void Thread1::run() 
{ 
    std::cout << "about to wait on semaphore 1\n"; 
    sem1.acquire(1); 
    //while (!sem1.tryAcquire(1, 200));  //works too 
    std::cout << "finished waiting on semaphore 1\n"; 
    sem2.release(1); 
} 

void Thread2::run() 
{ 
    std::cout << "signaling semaphore 1\n"; 
    sem1.release(1); 
    std::cout << "about to wait on semaphore 2\n"; 
    sem2.acquire(1); 
} 

main.cpp:

#include "threads.h" 
#include <iostream> 

int main(int argc, char *argv[]) 
{ 
    Thread1 t1; 
    Thread2 t2; 
    t1.start(); 
    t2.start(); 
    t1.wait(); 
    t2.wait(); 
    std::cout << "Success\n"; 
} 

sortie possible:

signaling semaphore 1 
about to wait on semaphore 2 
about to wait on semaphore 1 
finished waiting on semaphore 1 
Success 
+1

Astuce: votre exemple n'a pas besoin d'utiliser '' ni plusieurs fichiers. Utilisez 'qDebug() <<" Success ";' et n'utilisez qu'un seul "#include " dans 'main.cpp'. –

+0

@Kuba Ober threads.h est là à cause de moc, threads.cpp est là pour localiser les sémaphores dans une unité de traduction séparée. Et je préfère la bibliothèque standard du langage sur l'implémentation de Qt (question de goût) :-) – AMA

+0

J'ai supprimé les sémaphores et les ai remplacés chacun par un QWaitCondition et un QMutex et maintenant ça marche très bien. Je n'ai pas fait d'autres changements et je ne sais toujours pas pourquoi la version avec des sémaphores était incorrecte. Ils ont tous les deux été initialisés à 0. – user1576490