2017-01-12 2 views
0

Der folgende Code ist eine extreme Vereinfachung des eigentlichen Codes, mit dem ich es zu tun habe. Dies ist nur für jemanden, der in der Lage ist, das Problem zu reproduzieren, dem ich gegenüberstehe.Unerklärte Deadlock-Situation bei Verwendung des statischen Mutex in Funktion

#include <mutex> 
#include <thread> 

using std::mutex; 
using std::thread; 

void Do() 
{ 
    static mutex myMutex; 
    static int dataToProtect; 
    return; 
} 

class MyClass 
{ 
    public: 
     ~MyClass() 
     { 
     mythread_.join(); 
     } 


     void RunMyThread() 
     { 
     mythread_ = thread(&Do); 
     } 

     static MyClass *Instance() 
     { 
     static MyClass single; 
     return &single; 
     } 

    private: 
     MyClass() 
     {} 

     std::thread mythread_; 
}; 



int main() 
{ 
    MyClass::Instance()->RunMyThread(); 
    return 0; 
} 

Wenn mit gcc auf MinGW-w64 erfüllt, wird die Ausführung in fest:

static mutex myMutex; 

Es sieht aus wie die Kombination aus dem Faden und das Singleton Design dieses Problem schaffen, denn wenn ich telefoniere() ohne einen Thread zu verwenden:

void RunMyThread() 
    { 
    // mythread_ = thread(&Do); 
    Do(); 
    } 

das Programm wird bis zum Ende ausgeführt. Oder, wenn ich, indem die Konstruktor Öffentlichkeit rund um das Singleton-Design, und ich rufe RunMyThread() durch eine Instanz von MyClass:

int main() 
{ 
    // MyClass::Instance()->RunMyThread(); 
    MyClass o; 
    o.RunMyThread(); 
    return 0; 
} 

das Programm ausführt, als auch bis zum Ende.

Jetzt, wenn ich den ursprünglichen Code an der Spitze mit gcc unter Linux kompilieren, gibt es kein Problem. Das Programm wird bis zum Ende ausgeführt.

Ich kann nicht herausfinden, welches Verhalten in diesem Code plattformabhängig ist. Irgendeine Idee?

+0

Sind zwei Threads fest, oder nur einer? Haben Sie ihre Stack-Spuren untersucht, einschließlich der Demontage? Und wie weißt du das? Ein Problem, das Sie haben, ist, dass Ihr 'thread' nicht vor dem Ende von' main' endet und ich glaube, dass dies dazu führt, dass Ihr Verhalten im Standard unterspezifiziert ist ... – Yakk

+0

@Yakk Der Thread endet vor dem Ende von main, weil der Der Hauptthread wartet im MyClass-Destruktor für den untergeordneten Thread. Ich weiß, dass die Ausführung im Unterthread hängen bleibt, denn wenn ich den Unterbrechungspunkt auf "static mutex myMutex" setze, wartet der Hauptthread bereits auf den untergeordneten Thread bei "mythread_.join();" in MyClass-Destruktor. Wenn ich nun nach dem Punkt mit dem Debugger herüberkomme, bleibt die Ausführung hängen. Entschuldigung, ich habe nicht die Fähigkeiten, den Code zu disassemblieren. – Guett31

+1

Nicht der Hauptthread, sondern die 'Hauptfunktion'. Die Zerstörung der Funktionsstatik erfolgt nach dem 'Haupt'-Ende. Thread-Status und Verhalten nach "Haupt" -Enden ist nach meiner Erfahrung im Standard extrem unterspezifiziert. Beachten Sie, dass Text, der so aussieht, bedeutet, dass ich mich auf Wörter im Code beziehe. 'main' als ein Wort-in-Code tritt nur in C++ für die' main'-Funktion auf. So bezieht sich "Ende von' main' "auf das Ende der Sache, die in Ihrem Code' main' genannt wird. ;) – Yakk

Antwort

1

die bisherigen Kommentare/Antworten betrachtet, eine einfache Antwort auf die Frage ist: Erlauben ein Thread, nachdem die Hauptfunktion zurückkehrt auszuführen ist, was das undefinierte Verhalten führt. (Wenn Code-Portabilität erforderlich ist, sollte dies vermieden werden.)

1

Dies wird höchstwahrscheinlich durch die Reihenfolge verursacht, dass Dinge in der Windows-Laufzeit bereinigt werden. Sie können dies testen, indem Sie einen expliziten Aufruf an Ihre Klasse wie folgt ergänzt:

ShutDown() 
{ 
    mythread_.join(); 
} 

den Anruf aus dem destructor beitreten Nehmen. Dann in Ihrer Hauptfunktion:

int main() 
{ 
    MyClass::Instance()->RunMyThread(); 
    MyClass::Instance()->ShutDown(); 
    return 0; 
} 
Verwandte Themen