threads und externe variablen
-
Danke für die ganzen Antworten.
Habe mich ein wenig eingelesen und benutze eine critical section.
Habe auch volatile probiert aber beides kam zu keiner lösung.
Momentan hab ichs jetzt anders, ich habe eine Funktion
die einen vector prüft ob ein object mit einem
bestimmt wert vorhanden ist oder nicht, und gibt dann halt
true oder false zurück. Das heisst ich hab jetzt eine whileschleife
im Thread die bedingung ist das ein bool true ist.
Soo in der Whileschleife wird jetzt mit einer function
gecheckt ob in einem vector etwas vorhanden ist,
und wenn ja gibt diese funktion true zurück, wenn nicht dann false.
Diese funktion setzt auch die bool variable die die Bedingung ist.
Nun ist es leider so, das der vector innerhalb des Threads anscheinend
nicht geupdatet wird. Der Vector selber bekommt nebenbei neue werte,
löscht werte etc in dem mainprogramm. Damit es da keine Fehler gibt,
benutze ich wie vorher schon gesagt eine critical section und
EnterCriticalSection bzw LeaveCriticalSection. Kann es da trotzdem
noch probleme geben ? wenn ja welche ?
Weil naja, es klappt eigentlich das nebenbei sachen eingefügt bzw gelöscht
werden nur innerhalb des threads scheint die funktion das nicht mizukriegen.
-
Du hast irgendwo einen Fehler gemacht, aber wo, können wir auch nicht sagen ohne den Code zu sehen. Wenn Zugriffe auf gemeinsam genutzte Objekte mit critical sections synchronisiert werden, dann reicht das.
Du musst dich halt mit volatile dagegen absichern, dass der Compiler gut gemeinte Optimierungen anbringt.
Betrachte folgendes Beispiel:static bool quit; void thread() { quit=false; while (!quit) { //mach was } }Der Compiler kann sich jetzt while (true) denken, da sich der Wert von quit unter normalen Bedingungen nicht ändern kann. Wenn aber "abnormale" Bedingungen vorliegen, sprich, dass quit in einem anderen Thread verändert wird, musst du dich gegen solche Optimierungen mit volatile static bool quit absichern.
-
Sebastian Pizer schrieb:
????????????????????????? schrieb:
was soll das hier überhaupt bringen die Variable als extern zu deklarieren?
oder ist das eine Design-Frage, warum man so etwas jemals machen sollte?
Ja, hab extern noch nie gebraucht. Gibts da auch sinnvolle Beispiele, für Threads brauch ich es nicht.
-
beginner31231 schrieb:
Habe mich ein wenig eingelesen und benutze eine critical section.
Habe auch volatile probiert aber beides kam zu keiner lösung.volatile ist Blödsinn hier. Ein(e) Mutex/CriticalSection ist vernünftig und funktioniert auch bei richtiger Anwendung.
beginner31231 schrieb:
Kann es da trotzdem noch probleme geben ? wenn ja welche ? Weil naja, es klappt eigentlich das nebenbei sachen eingefügt bzw gelöscht werden nur innerhalb des threads scheint die funktion das nicht mizukriegen.
Dann hast Du wohl etwas falsch gemacht.
Ich denke, Du solltest Dich "noch mehr einlesen" in die Materie.
Gruß,
SP
-
-
Athar schrieb:
Sebastian Pizer schrieb:
volatile ist Blödsinn hier.
Wie kommst du darauf?
siehe Link!
-
Sebastian Pizer schrieb:
siehe Link!
... und was willst du damit sagen? Da wird der Sinn von volatile beschrieben.
Wenn er auf die Veränderungen irgendwelcher Flags von außen wartet, muss er es hier höchstwahrscheinlich einsetzen. Um darüber eine Aussage treffen zu können, müsste man aber erstmal Code sehen.
-
Athar schrieb:
...irgendwelcher Flags von außen wartet, muss er es hier höchstwahrscheinlich einsetzen.
Was für "Flags von außen"? Ich gehe nicht davon aus, dass der OP Gerätetreiber programmieren will.
Entweder wird der Zugriff auf ein gemeinsames "Objekt" über einen Mutex synchronisiert (ist am einfachsten und weniger fehleranfällig), oder mit so etwas wie spinlocks + memory barrier -- lezteres erfordert aber atomare lese/schreib/austausch-Operationen, die
volatile(aus C und C++) nicht garantiert. Außerdem ist das eine ziemliche low-level Frickelei, welche man nur Experten überlassen sollte. Ich zähle mich übrigens nicht zu dieser Experten-Gruppe.Gruß,
SP
-
Naja das was ich mache ist, das vor der ersten benutzung einmal
InitializeCriticalSection aufgerufen wird, und dann vor jedem
zugriff auf den Vector EnterCriticalSection, und danach LeaveCriticalSection
calle. Hab ich da irgendwas verpasst ? :>
Mit volatile werd ichs nochmal probieren ^^
-
edit:
Das Problem ist nicht die Bool Variable.bool funktion(int id) { if(!initalized) { InitializeCriticalSection(&crit); initalized = true; } vector<example>::iterator it; EnterCriticalSection(&crit); it = structvector.begin(); while(it != structvector.end()) { if (it->id == id) { LeaveCriticalSection(&crit); return true; } else it++; } LeaveCriticalSection(&crit); return false; }So in etwa sieht die checkfunktion aus. Mach ich da irgendwas falsch ?
Da sieht man auch direkt wie ich die Critical Section verwende halt vor jedem
zugriff auf den Vector.
Die Schleife die das testet hat auch einen Sleep und testet nicht durchgehend.
ca so:while(boolvar) { Sleep(2000); boolvar = function(struct->id); }Wenn daran irgendwas falsch ist, wäre es nett mehr zu sagen
was ich falsch mache und wieso das falsch ist. Vielen dank
das ihr euch solche Mühe gebt
-
beginner31231 schrieb:
Mach ich da irgendwas falsch ?
Ja, denn die Initialisierung von crit erzeugt eine race condition, z.B.
// Thread 1 | Thread 2 if(!initalized) | if(!initalized) { | { InitializeCriticalSection(&crit); | initalized = true; | } | vector<example>::iterator it; | EnterCriticalSection(&crit); | | InitializeCriticalSection(&crit); | initalized = true; | } | vector<example>::iterator it; | EnterCriticalSection(&crit); // upsStatements, die in der gleichen Zeile stehen, stelle man sich als gleichzeitig ausgeführt vor.
Das Synchronisationsobjekt muss natürlich initialisiert worden sein, bevor mehrere Threads versuchen können, dieses zur Synchronisation zu verwenden. Zweckmäßigerweise macht man das also gleich bei der Erzeugung des zu schützenden vector.
Die Benutzung von RAII ist zu empfehlen.
-
Danke für die Informationen. Nunja, zu der Sache gleich bei der Erzeugung.
Ich habe den Vector nicht in dem mainprogramm sondern in einer anderen
cpp datei. Das heißt ich müsste den vector schon im main Programm erzeugen
und dann in der anderen cpp als extern angeben ?
Sprich ich müsste das im main Programm ca so machen -->CRITICAL_SECTION crit; InitializeCriticalSection(&crit); vector<example>vectorname;und in der anderen cpp dann halt
extern vector<example>vectorname;und wie vorher dann enter bzw leave benutzen nur
das initialize natürlich rausnehmen dann ?
Bei der erzeugung müsste ich jetzt nicht EnterCriticalSection benutzen ?!
Vielen dank nochmal für die Hilfe.
-
beginner31231 schrieb:
Danke für die Informationen. Nunja, zu der Sache gleich bei der Erzeugung.
Ich habe den Vector nicht in dem mainprogramm sondern in einer anderen
cpp datei. Das heißt ich müsste den vector schon im main Programm erzeugen
und dann in der anderen cpp als extern angeben ?
Sprich ich müsste das im main Programm ca so machen -->CRITICAL_SECTION crit; InitializeCriticalSection(&crit); vector<example>vectorname;und in der anderen cpp dann halt
extern vector<example>vectorname;und wie vorher dann enter bzw leave benutzen nur
das initialize natürlich rausnehmen dann ?
Bei der erzeugung müsste ich jetzt nicht EnterCriticalSection benutzen ?!
Vielen dank nochmal für die Hilfe.Das ist korrekt, mein Herr!