wxWidgets threads
-
So, die sockets laufen, jetzt hab ich im wxWidgets Buch weitergelesen und festgestellt, dass ich für die sockets einen thread brauch. Leider versteh ich die Benutzung von wxMutex noch nicht so ganz.
// this variable has an "s_" prefix because it is static: seeing an "s_" in // a multithreaded program is in general a good sign that you should use a // mutex (or a critical section) static wxMutex *s_mutexProtectingTheGlobalData; // we store some numbers in this global array which is presumably used by // several threads simultaneously wxArrayInt s_data; void MyThread::AddNewNode(int num) { // ensure that no other thread accesses the list s_mutexProtectingTheGlobalList->Lock(); s_data.Add(num); s_mutexProtectingTheGlobalList->Unlock(); } // return true the given number is greater than all array elements bool MyThread::IsGreater(int num) { // before using the list we must acquire the mutex wxMutexLocker lock(s_mutexProtectingTheGlobalData); size_t count = s_data.Count(); for ( size_t n = 0; n < count; n++ ) { if ( s_data[n] > num ) return false; } return true; }
Anscheinend blockiert jetzt so ein Mutex alle global Variablen. Aber was passiert jetzt genau, wenn beide threads gleichzeitig auf das Array zugreifen wollen? Beide locken gleichzeitig? Geht irgendwie nicht. Es gibt nen Fehler bei der lock-Funktion? Der eine thread wartet solange bis der andre fertig ist?
Schon mal danke im voraus.
-
Wenn zwei deiner Mutex versuchen, einen Lock zu setzten, wartet einer der beiden Threads, bis der andere den Mutex wieder freigibt.
-
Ah, danke. Ist also stark vereinfacht sowas wie:
bool isLocked = false; //globale Variable void lock() { while(isLocked); isLocked = true } void unlock() { isLocked = false; }
-
kynarion schrieb:
Ah, danke. Ist also stark vereinfacht sowas wie: [...]
Vom Prinzip her, ja. Die Umsetzung in der Praxis ist aber um einiges komplexer...
-
Hallo!
Ist das in dem Beispiel ein Schreibfehler oder Absicht, daß einmal
s_mutexProtectingTheGlobalList und an anderer Stelle
s_mutexProtectingTheGlobalData verwendet wird?Ich habe versucht, die Befehle 1:1 in mein Programm zu kopieren, aber erhalte haufenweise Fehlermeldungen. Was mache ich falsch?
Der eine Thread soll aus X Y berechnen und X inkrementieren, der andere Thread soll X und Y ausgeben, ohne daß Thread1 gerade mitten in der Berechnung ist.
Die Sleep-Befehle sind Absicht, damit möglichst viel Unsynchronität entsteht.static wxMutex *s_mutexProtectingTheGlobalData; struct MyThread1 : wxThread { ThreadsFrm* window; bool stop; MyThread1(ThreadsFrm* p) { stop = false; window = p; } wxMutexLocker lock(s_mutexProtectingTheGlobalData); virtual ExitCode Entry() { while(!stop) { (*window->WxMemo1) << "x: " << global_x << " -> " << global_y << "\r\n"; Sleep(1000); } (*window->WxMemo1) << "Thread1 fertig!\r\n"; return 0; } }; struct MyThread2 : wxThread { ThreadsFrm* window; bool stop; MyThread2(ThreadsFrm* p) { stop = false; window = p; } s_mutexProtectingTheGlobalList->Lock(); virtual ExitCode Entry() { while(!stop) { global_x++; Sleep(100); global_y = global_x * 10; Sleep(100); } (*window->WxMemo1) << "Thread2 fertig!\r\n"; return 0; s_mutexProtectingTheGlobalList->Unlock(); } };
11 `s_mutexProtectingTheGlobalData' is not a type 11 ISO C++ forbids declaration of `parameter' with no type 31 ISO C++ forbids declaration of `s_mutexProtectingTheGlobalList' with no type 31 expected `;' before '->' token In member function `virtual void* MyThread2::Entry()': 42 `s_mutexProtectingTheGlobalList' was not declared in this scope 42 [Warning] unused variable 's_mutexProtectingTheGlobalList'
Ich habe bereits versucht, die Lock/Unlock-Befehle an verschiedene Stellen zu schieben, aber keine wirkliche Verbesserung bemerkt.
PS: Das ist nur ein Übungsbeispiel, mir ist klar, daß die Aufgabe eigentlich keine Threads braucht.
PPS: meine Kenntnisse sind im Moment auf Stufe 0, aber ich muß in möglichst kurzer Zeit durch sämtliche Themen durch...
-
Ich hab es jetzt so gelöst:
wxMutex schloss; //Mutex-Variable
dann jeweils in den Threads:
wxMutexLocker lock(schloss);
...
wxMutexLocker unlock(schloss);Und das funktioniert!
Ich würde natürlich trotzdem gern wissen, warum es auf die andere Weise nicht geht.