Mehrere Threads mit gleicher ThreadProc
-
Bakc on topic
Der TLS ist eine vom Betriebssystem extra bereitgestellter Threadspezifischer Speicherbereich. Wenn man den nicht explizit anfragt, speichert man da auch nichts. Variablen auf dem Stack landen da jedenfalls nicht. Trotzdem sind die Stacks wie gesagt unabhängig voneinander.
Globale Variablen oder welche aufm Heap die außerhalb der ThreadProc erstellt wurden, müssen per Mutex oder Critical Section vor Mehrfachzugriff geschützt werden. Am besten schaust du dir dazu CreateMutex, WaitForSingleObject bzw. CreateCriticalSection, EnterCriticalSection, LeaveCriticalSection an. Für deinen Bedarf, kommt mir zweiteres passender vor.
Die Sache mit _beginthread ist übrigens nicht Borland-spezifisch, zumindest der VC hat sowas auch. Ich schätze alles in allem trifft das auf jede Runtime-Library zu, da jede Library irgendwann threadspezifisch was hat und das muss nunmal initialisiert werden.
-
Vielen Dank, TriPhoenix´! Endlich mal einer, der etwas informatives von sich gibt.
Nocheinmal eine Information zu meinen Variablen (wie ich es bisher gemacht habe):
Ich habe eine Threadklasse erstellt, in der die Informationen für jeden Thread gespeichert sind, und für jeden Thread wird eine Instanz davon auf dem Heap erstellt und die Members gefüllt (ebenfalls auf dem Heap). Das heißt: Die Infos der einzelnen Threads überschneiden sich nicht (sind eh nur jeweils 3 WCHAR-Zeiger). Überdies lese ich innerhalb der ThreadProc nur von diesen Adressen.
Jo, so sieht das bisher aus. Ich hab auch noch keine Fehlermeldungen während der Laufzeit bekommen. Ich stelle mir den Umgang mit Threads und dem Speicher so vor:Alle Threads teilen sich den gleichen Heap. Wenn sich Threads aber auch die gleichen Informationen auf dem Heap teilen, muss man eben CriticalSections verwenden.
Ist diese Vorstellung richtig?
Eine zweite Frage hätte ich interessenhalber da noch:
Der TLS ist eine vom Betriebssystem extra bereitgestellter Threadspezifischer Speicherbereich. Wenn man den nicht explizit anfragt, speichert man da auch nichts.
Ist das also sozusagen ein Bereich auf dem Heap, der nur für den Thread reserviert ist, der ihn erfragt? Und wie stelle ich diesen bereit/erfrage ich ihn?
-
Original erstellt von WebFritzi:
**Ich habe eine Threadklasse erstellt, in der die Informationen für jeden Thread gespeichert sind, und für jeden Thread wird eine Instanz davon auf dem Heap erstellt und die Members gefüllt (ebenfalls auf dem Heap). Das heißt: Die Infos der einzelnen Threads überschneiden sich nicht (sind eh nur jeweils 3 WCHAR-Zeiger). Überdies lese ich innerhalb der ThreadProc nur von diesen Adressen.
**Sehr gut, dann solltest du keine Probleme haben
**
Jo, so sieht das bisher aus. Ich hab auch noch keine Fehlermeldungen während der Laufzeit bekommen.
**Das ist leider die Tücke mit Multithreading, es mag hundertmal gut gehen und beim hundertersten mal schief
Aber wie gesagt, sieht bei dir alles sicher aus.
**
Ich stelle mir den Umgang mit Threads und dem Speicher so vor:
*
Alle Threads teilen sich den gleichen Heap. Wenn sich Threads aber auch die gleichen Informationen auf dem Heap teilen, muss man eben CriticalSections verwenden.
*Ist diese Vorstellung richtig?
**Exakt. Ums noch weiter zu führen teilen sich Threads fast alles, also auch globale Variablen etc. Nur Stack (damit lokale Variablen) und TLS sind strikt getrennt.
**
Eine zweite Frage hätte ich interessenhalber da noch:
[quote]
Der TLS ist eine vom Betriebssystem extra bereitgestellter Threadspezifischer Speicherbereich. Wenn man den nicht explizit anfragt, speichert man da auch nichts.
****
Ist das also sozusagen ein Bereich auf dem Heap, der nur für den Thread reserviert ist, der ihn erfragt? Und wie stelle ich diesen bereit/erfrage ich ihn?**[/QUOTE]
Da muss ich mal kurz nachschlagen *schweresbuchausregalzieh*. Man unterscheidet zwei sorten von TLS, dynamischen und statischen.
Dynamischer TLS: Dieser TLS ist im Prinzip ein Array aus PVOIDs mit der Größe TLS_MINIMUM_AVAILABLE, für jeden Thread eines. Zusätzlich hält Windows pro Prozess ein Array aus booleans um zu checken welche Indizes belegt sind. Per DWORD TlsAlloc(); kann man einen Index belegen, Windows liefert den Index (oder 0xffffffff für den Fehlerfall) zurück. Dann kann jeder Thread (die Alloziierung macht man vor der Starten dre Threads) in "seinem" array per BOOL TlsSetValue(DWORD index, PVOID value); die Werte setzen und per PVOID TlsGetValue(DWORD index); wieder holen. Sclhießlich kann man per BOOL TlsFree(DWORD index) den Index wieder freigeben. So kann jeder Thread quasi ein paar daten für sich speichern.
Statischer TLS: Hier kann ich nur für MSVC sprechen, da der laut meinem Buch per __declspec gemacht wird und ich nicht weiß, inwiefern andere Compiler sowas haben. Deklariert man eine Variable nämlich dort in dieser Form:
__declspec(thread) DWORD meineVariable = 0;
Dann hat jeder Thread eine eigene Kopie dieser Variablen. Da dies dann in der fertigen Win32-EXE in einem Extra-Abschnitt landet, hat vermutlich jeder Win32-Compiler eine Methode dafür. In der MSVC-Hilfe findet ischs z.B. direkt unetr "Thread local storage (TLS)".[ Dieser Beitrag wurde am 31.03.2003 um 02:16 Uhr von TriPhoenix editiert. ]
-
Geil! Dankeschön.
Deinen Text speichere ich mir für den Fall, dass ich sowas mal brauche. ocheinmal vielen Dank. *freu*