Critical Sections / Multithreading
-
Hallo,
ich habe eine Datenbank, auf die mehrere Threads gleichzeitig zugreifen. Es ist eine SQLite Datenbank, die aber keine gleichzeitigen Zugriffe erlaubt.
Ich wollte mir deshalb mit Critical Sections Abhilfe verschaffen.
Die Datenbank-Schnittstelle ist in einer Klasse drin, alle Threads verwenden dieselbe Instanz der Klasse. Ich habe nun ein privates CRITICAL_SECTION-Objekt in der Klasse und ich habe alle public Funktionen (also die, die von den Threads aufgerufen werden können) so aufgebaut:int klasse::beispielfunktion() { EnterCriticalSection(&m_cs); int iReturn; // tue etwas..., lese oder schreibe aus/in DB LeaveCriticalSection(&m_cs); return iReturn; }Den Teil zwischen Enter und Leave müsste jetzt nur von _einem_ Thread gleichzeitig durchlaufbar sein, oder? Und das bei allen Funktionen, die mit demselben Objekt (m_cs) arbeiten?!
Wäre es hier nicht theoretisch möglich, dass nach Leave der nächste Thread bei derselben Funktion zum Zug kommt, iReturn mit etwas anderem füllt, dann wieder der erste Thread drankommt und iReturn zurückgibt, was allerdings vom nächsten Thread überschrieben wurde? Oder wird diese Variable hier dann im Speicher 2x angelegt?
Weil irgendwie stürzt mein Programm bei vielen gleichzeitigen Zugriffen der Threads ab, ich weiß aber nicht warum
Danke im Voraus!
MfG
-
Ne, jeder Thread hat seinen eigenen Stack.
-
Thread-Synchronisation innerhalb der Klasse würde ich glaube ich hier auch nicht machen. Das ist zwar einfacher zu handhaben (so nach dem Motto: die Synch. wird intern geregelt) aber das kann auch mal zu Fehlern führen (wie man sieht
). Sowas ist dann schlecht nachvollziehbar.Hm, ich kann zu Deinem Fehler so natürlich nicht viel sagen, aber probiers doch (wenigstens testweise) mal nach diesem Schema:
EnterCriticalSection(&lock); obj.MethodCall(blupp); LeaveCriticalSection(&lock);PS: Jeder Thread hat zwar sein eigenes Stack, aber nicht sein eigenes Heap (-> new/delete!).
-
Hallo,
Danke für die Antworten :).
@CodeFinder: würde sich mir denn eine Alternative anbieten? Also die SQLite datenbank erlaubt halt nur einen Zugriff gleichzeitig ^^. Eine Möglichkeit wäre hier wohl eine job-Queue, die ein weiterer Thread nacheinander abarbeitet, oder?
Ja, um sicher zu gehen habe ich das auch so ähnlich gemacht (damit ich nicht irgendwo was vergesse), für jede public-Funktion:class db { public: bool machedies(int x) { EnterCriticalSection(&m_cs); bool bRet = machedies_intern(x); Leave...(); return bRet; } bool machedas(int x) { EnterCriticalSection(&m_cs); bool bRet = machedas_intern(x); Leave...(); return bRet; } private: bool machedies_intern(int x); bool machedas_intern(int x); };Inwiefern ist das fehleranfällig?
[edit]
oder meintest du dass das Enter/Leave komplett außerhalb der Klasse stattfinden soll? Würde das hier irgendwo einen Utnerschied machen?
Ich glaube ich entscheide mich doch für die Job-Queue.
-
Es macht keinen Unterschied ob du "innen" oder "aussen" synchronisierst, ist beides OK.
Und das mit der lokalen Variable ist definitiv KEIN Problem.