2016-04-25 9 views
1

Ich bin neu in C++ und experimentiere ein bisschen herum. Ich habe angefangen einen Thread mit der CreateThread-Methode zu erstellen. Ich gebe auch einen Zeiger auf eine struct-Methode, die einen Test-Wert verweist. So weit, ist es gut. Jetzt habe ich den Wert geändert, bevor ich den Thread auf 0 setze. Wenn ich das Programm starte, scheint alles wie erwartet zu funktionieren. Aber wenn ich den Wert auch nach der CreateThread-Methode (auf 1) ändere, gibt der Thread immer 1 aus. Ich erwartete eine Ausgabe von 0, weil ich dachte, dass Änderungen an einer Variablen den Thread nicht beeinflussen. Oder zumindest eine Ausgabe von 0 zuerst und dann 1.Anormale Ausgabe von Windows-Thread in C++

Jetzt habe ich etwas getestet: Wenn ich den Haupt-Thread z. B. warten 5000ms, dann ist die Ausgabe des Threads wieder immer 0. Aber ohne es ist wieder 1.

Ich hoffe, Sie können mir mit dem Verständnis dieses Problems helfen. Hier

ist ein Code:

struct TESTSTRUCT{ 
    int test; 
}; 

DWORD WINAPI testFunc(void* lpParam){ 

    TESTSTRUCT& params=*((TESTSTRUCT*)lpParam); 

    int a=params.test; 

    while(true){ 
     cout << a; 
     Sleep(5000); 
    } 

    return 0; 
} 

int main(int argc, char *argv[]) { 

    TESTSTRUCT teststr; 
    teststr.test=0; 
    HANDLE myhandle; 
    myhandle = CreateThread(0, 0, testFunc, &teststr, 0, 0); 

    Sleep(5000); // If left out, thread outputs always 1! 

    teststr.test=1; 

    cout << "main" << teststr.test; 

    CloseHandle(myhandle); 

    MSG msg; 
    while(GetMessage(&msg, NULL, 0, 0)) 
    { 
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
    } 
} 
+0

Das Betriebssystem entscheidet, wann "teststr.test" zugewiesen wird. Dies ist eine klassische Race-Bedingung, die in der Regel durch Sperren behandelt wird. –

+0

Sind Sie sicher? Ich meine, es ist in der Hauptfunktion und jemand würde erwarten, ersten Wert 0 und 1 zuzuweisen. Oder kompiliert der Compiler in umgekehrter Reihenfolge? (von unten nach oben zum Beispiel). – Sully

Antwort

0

sehen:

myhandle = CreateThread(0, 0, testFunc, &teststr, 0, 0); 

Sie passieren Ihre teststr unter Bezugnahme auf Ihre testFunc. Daher arbeiten Ihre main Methode und Ihre testFunc mit den gleichen Daten. Das Ändern eines beeinflusst das andere.

klar zu sein, wie es funktioniert, ist, dass Sie die Adresse von teststr bekommen, es zu void* Gießen und dann innerhalb testFunc Sie es zurück zu TESTSTRUCT& werfen. Dies ist die gleiche Sache, als wenn Sie teststr auf testFunc als Referenz übergeben haben.

Ich sollte erwähnen, dass ohne Sperrung Sie eine Race-Bedingung auf den Ausgang des Threads haben, egal, was die Schlafzeit ist. Lass main lange genug schlafen und im Allgemeinen siehst du, dass dein Thread den "alten" Wert ausgibt, aber es gibt keine Garantie.

+0

Okay, das macht jetzt Sinn! Aber wie kann ich es vermeiden, da die CreateThread-Methode nur erlaubt, Zeiger zu übergeben. Ich möchte nur erreichen, dass die Threads die Werte behalten, die sie erhalten haben. Wie soll ich das machen? – Sully

+1

Es ist sicher, einen Integer-Wert der passenden Größe auf einen void-Zeiger und zurück zu übertragen. Aber im allgemeinen Fall könnten Sie einfach eine Kopie der Daten erstellen und dem Thread einen Zeiger auf die Kopie übergeben. (In der Praxis muss der Haupt-Thread meistens nicht auf die Daten zugreifen, die Sie an den neuen Thread übergeben haben. Sie müssen also nichts tun.) –

+0

Nun, ich habe es auch mit einem globalen Int versucht -Variable. Ich habe einen Mutex für den Cout eingerichtet, aber es scheint, dass der erstellte Thread die globale Variable nicht kopiert. Wenn ich also zuerst die Variable auf 0 setze, erzeuge den Thread und setze dann die Variable wieder auf 1, der erzeugte Thread gibt immer noch 1 aus. Ich verstehe das nicht wirklich. Bei einer Struktur funktioniert alles wie erwartet, aber nicht mit einer einfachen Variablen. Warum ist das so? – Sully