WinAPI und Multithreading Synkronisationsproblem
-
Hallo ich habe unter Linux die PThreads verwendet und benutze da hauptsächlich mutex und conditions...
jetzt will ich das unter Windows programmieren...
In der API hab ich CriticalSections gefunden... die ich anstelle von mutex(linux) verwende...
Was aber verwende ich anstelle von conditions? Auch in der API finde ich CONDITION_VARIABLE.. leider wird diese nicht in winXP zur Verfügung gestellt......also habe ich versucht mit Events rumzuspielen.
Was muss ich dabei beachten? Denn ich denke, dass es prinzipiell schon funktioniert.. allerdings wenn sich ein Thread beenden, bekomme ich eine Fehlermeldung, dass mein Programm beendet werden musste... Problembericht senden!? DIALOG... leider liefert der mir keine genaue Aussage über den Fehler...
...also ich weiss nicht genau, was schief geht!

// Am Start HANDLE cond = CreateEvent( NULL, FALSE, FALSE, NULL ); // Zwischen drin // Thread 1 WaitForSingleObject( cond, INFINITY ); // Thread 2 SetEvent( cond ); // Am Ende CloseHandle( cond );DWORD WINAPI Thread::static_runner( LPVOID data ) { // Hier rufe ich Thread 1 und 2 auf... // Wenn jetzt einer von beiden diese stelle hier erreicht // Schmiert mir das Programm ab... wenn ich versuche Sleep( 2000 ); // oder ExitThread( 0 ); // aufzurufen... Ausgabe wie std::cout << "Huhu" << std::endl; // funktionieren aber noch return 0; }
-
Hab hier jetzt eine Loesung zusammengeschusster:

#include <iostream> #include <stdlib.h> #include <windows.h> using namespace std; class Runnable { public: virtual void run() = 0; }; class Thread { private: HANDLE th; DWORD mtid; Runnable* mr; public: Thread( Runnable& r ){ th = 0; mr = &r; } ~Thread(){ if( th != 0 ){ CloseHandle( th ); } } static DWORD WINAPI static_caller( LPVOID data ){ Runnable* r = (Runnable*)data; r->run(); cout << " *** THREAD BEENDET ***" << endl; ExitThread( 0 ); return 0; } void start(){ th = CreateThread( 0, 0, static_caller, (LPVOID)mr, 0, &mtid ); } }; class Semaphor { private: int mittel; CRITICAL_SECTION cs; HANDLE condition; void lock(){ EnterCriticalSection( &cs ); cout << " > lock" << endl; } void unlock(){ cout << " < unlock" << endl; LeaveCriticalSection( &cs ); } public: Semaphor( int m ){ mittel = m; InitializeCriticalSection( &cs ); condition = CreateEvent( NULL, FALSE, FALSE, NULL ); } ~Semaphor(){ CloseHandle( condition ); DeleteCriticalSection( &cs ); } void erwerben(){ lock(); while( mittel <= 0 ){ unlock(); WaitForSingleObject( condition, INFINITE ); lock(); } mittel--; unlock(); } void zurueckgeben(){ lock(); mittel++; unlock(); SetEvent( condition ); } }; class Programm : public Runnable { private: static Semaphor* sem; int mZeit; int mId; public: Programm( int zeit, int id ){ mZeit = zeit; mId = id; } virtual ~Programm(){ } void run(){ Sleep( mZeit ); cout << "Ich bin Thread: " << mId << endl; if( mId == 1 ){ cout << "Thread: " << mId << " gebe Sem zurueck" << endl; sem->zurueckgeben(); }else{ cout << "Thread: " << mId << " erwerbe Sem" << endl; sem->erwerben(); cout << "Thread: " << mId << " gebe Sem zurueck" << endl; sem->zurueckgeben(); } cout << "Thread: " << mId << " verabschiedet sich" << endl; } }; Semaphor* Programm::sem = new Semaphor( 0 ); int main( int argc, char** argv ) { Programm p1( 3200, 1 ); Programm p2( 1700, 2 ); Programm p3( 1500, 3 ); Thread t1( p1 ); Thread t2( p2 ); Thread t3( p3 ); t1.start(); t2.start(); t3.start(); while( true ){ cout << "Schlafe..." << endl; Sleep( 20000 ); } }
-
Semaphoren musst du nicht nachbauen, die gibts schon fertig.
(Auch Mutexe, obwohl da, wenn nicht prozessübergreifend benutzt, eher CriticalSections anzuwenden sind, weil sie performanter sind).http://msdn.microsoft.com/en-us/library/ms686360(VS.85).aspx
SimonEdit: Ausserdem ist es ratsam RAII für die "Lock" Geschichten zu verwenden.
-
boost::thread bzw boost::mutex sind zwei heiße Tipps.
-
Also bis jetzt läuft die Lösung ganz gut.. und ich bin an keine extra Bibliothek gebunden

am liebsten wären mir ja systemcalls 
also falls wer ein gutes tut hat

-
Sorry, daß ich mir nicht die Muße genommen habe, Deinen Code zu lesen.
Dafür hab ich Deinen Wunsch erhört:
matti83 schrieb:
am liebsten wären mir ja systemcalls 
also falls wer ein gutes tut hat

Bitteschön, hier:
http://www.jliforum.de/board/viewtopic.php?p=63665
http://www.codeworx.org/cpp_tuts_1_5.php
Multithreading for Rookies: http://msdn.microsoft.com/en-us/library/ms810438.aspxHTH,
Martin
-
Also bis jetzt läuft die Lösung ganz gut.. und ich bin an keine extra Bibliothek gebunden
Wenn es dich nicht stört dass du ne Race-Condition drinnen hast...
-
eine race condition?
weitere Erläuterung bitte.. und warum ist das schlecht?
@Mmacher - danke für die links...