Ich nicht, ich denke es wird schimmer seinKaeru Gaman hat geschrieben: aber was auch immer das ist, ich bezweifle einfach mal,
dass es eine ähnlichkeit mit dieser extremen versuchsanordnung hat.
Variable als Flag zur Threadsicherheit
- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

-
Kaeru Gaman
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
ich habe nachgewiesen, dass es sich nicht hängt sondern nur schweinelange dauert.
somit ist meine aussage vom anfang gestützt, die verwaltung der globalen counter sei problemlos.
kannst ja mal gucken, wie lange deine 100 threads brauchen...
Code: Alles auswählen
Global glob.l
Dim Threads.l(99)
#LastThread = 99
Procedure Thread(dummy.l)
Repeat
glob + 1
ForEver
EndProcedure
Debug "Label 1"
time = ElapsedMilliseconds()
For I = 0 To #LastThread
Debug "starting No. "+Str(I)
Threads(I) = CreateThread(@Thread(), 0)
Next
time = ElapsedMilliseconds() - time
Debug time
Debug "Label 2"
Delay(5000)
Debug "Label 3"
For I = 0 To #LastThread
KillThread(Threads(I))
Next
Debug "Label 4"
Debug globDer Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
- remi_meier
- Beiträge: 1078
- Registriert: 29.08.2004 20:11
- Wohnort: Schweiz
Vielleicht hilfts ja:
http://www.purebasic-lounge.de/viewtopi ... highlight=
http://www.purebasic-lounge.de/viewtopi ... highlight=
- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
@remi_meier
Das liest sich, als ob es mehrere Mutexe gibt, es gibt aber doch nur einen für alle Objekte, globalen Variablen usw.
Sonst müßte man ja bei der Erstellung des Mutex angeben, wofür er ist
Gruß
Thomas
Das liest sich, als ob es mehrere Mutexe gibt, es gibt aber doch nur einen für alle Objekte, globalen Variablen usw.
Sonst müßte man ja bei der Erstellung des Mutex angeben, wofür er ist
Gruß
Thomas
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

- remi_meier
- Beiträge: 1078
- Registriert: 29.08.2004 20:11
- Wohnort: Schweiz
Ich erstelle für mehrere Objekte auch mehrere Mutexes?
Ein Mutex ist eine CriticalSection von Windows.
Code: Alles auswählen
mutex1 = CreateMutex()
mutex2 = CreateMutex()
Debug mutex1
Debug mutex2- ts-soft
- Beiträge: 22292
- Registriert: 08.09.2004 00:57
- Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel - Wohnort: Berlin
Und woher weiß mutex1 was er schützen soll, verstehe ich nicht so ganz 
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.

-
Toshy
- Beiträge: 713
- Registriert: 22.03.2005 00:29
- Computerausstattung: Computer und Strom vorhanden
- Wohnort: LK Wolfenbüttel
@Kaeru Gaman
@ts-soft
Na ja, also ich versuche es natürlich mit so wenig Threads wie möglich, aber es könnte natürlich wirklich zu vielen Threads kommen. Aber es geht ja nicht und die Anzahl, sondern das Prinzip. Möchte logischer Weise solche unnötigen Fehlerquellen ausschließen.
@Kaeru Gaman
@all
Es war ursprünglich also schon so, das die selbe Procedure als Thread ausgeführt werden solle (dutzendfache oder mehr, natürlich nur wenn je gebraucht). Eingehende Daten (z.B. Netzwerk) müsten Zeitintensiv (also länger als nur 5 oder 10ms) verarbeitet werden, die jeweiligen Daten werden dann aus einer "Liste" rausgeholt und von einem freien Thread (der wartet) verarbeitet, ob nun ein Thread nur einen oder mehrere "Listeneinträge" abarbeitet weiß ich noch nicht. Nun aber geht es nur um einige (erstmal 2-4 Threads) die so unabhängig wie möglich sind, um keine wartezeiten auszulösen (wie bei Mutex), dazu nutze ich Flags die ihn ihrer Nutzung aber sicher sind (insoweit das hier geklärte zutriff).
Dabei ging es mir in erster Linie natürlich darum, das es nicht zu Abstürzen oder fehlerhaften Ergebnissen kommt. Das sogar die Berechnung nacheinander ausgeführt wird, ist ein angenehmer Nebeneffekt, daß alles etwas einfacher macht, da man direkt nach dem setzen der Daten in einem Thread diese mit einem anderen auslesen kann ohne das die Daten vielleicht noch nicht "ganz berechnet" wurden.
Da ich gerade so einen Teil bearbeite nehme ich das also als Beispiel:
Da ich nun von vielen Clienten Daten empfange, diese in einen Buffer schreiben muß und dann ständig überprüfen muß was an Daten da sind um sie ab einem bestimmten Zeitpunkt zu bearbeiten, geht das nur sinnvoll mit Threads. Dabei schreibt z.B. ein Haupthread die Networkdaten in einen Speicherbereich, ein anderer Thread lies und überprüft diese und bei bedarf löscht er diese. Natürlich kann es dazu kommen, das wenn zwei Thread gleichzeitig auf diesen Bereich zugreifen, dies fehlschlägt, weil ein neuer Speicherbereich allokiert wurde.
Erstelle ich nun z.b. dafür immer wieder ein Mutex gibt es ähnliche Probleme wie beim erstellen von Threads, es dauert einfach so lang, das der ZEitgewinn durch die Threadverarbeitung mehrfach wieder dahin gerafft wird. Also muß ich es auf eine einfach und schnelle Weise machen und das geht mit einfachen Variablen (am besten in Strukturen) am besten.
Verinfacht gesagt stimmt das wohl so. Zwar muß ich testen, wie es dann mit dem Abfragen des Inhalt und dem damit verbundenen Timing aussieht, aber meine Frage Frage hast du richtig verstanden.soweit ich das verstanden habe,
geht es toshy um gemeinsamen zugriff auf eine global-steuerung von mehreren threads aus,
und das läuft bei mir problemlos.
@ts-soft
*grins*Bei mir hängt sich das meist auf, und es sind nur 100 Threads, wie ich
Toshy einschätze möchte er mehr erstellen Satisfied Smile
Na ja, also ich versuche es natürlich mit so wenig Threads wie möglich, aber es könnte natürlich wirklich zu vielen Threads kommen. Aber es geht ja nicht und die Anzahl, sondern das Prinzip. Möchte logischer Weise solche unnötigen Fehlerquellen ausschließen.
@Kaeru Gaman
Normal zwar nicht, aber bei einer Procedure hätte das sogar passieren können, nur habe ich das jetzt erstmal etwas umgeplant. z.B. bei der Verarbeitung von eingehenden Networkdaten die etwas zeitintensiver sind, hätte das vorkommen können. Aber das werde ich nun erst später wenn es notwendig wird einbauen.egal wie viele threads Toshy verwenden will,
er wird bestimmt nicht hunderte derselben einfachen endloszähler starten wollen.
@all
Es war ursprünglich also schon so, das die selbe Procedure als Thread ausgeführt werden solle (dutzendfache oder mehr, natürlich nur wenn je gebraucht). Eingehende Daten (z.B. Netzwerk) müsten Zeitintensiv (also länger als nur 5 oder 10ms) verarbeitet werden, die jeweiligen Daten werden dann aus einer "Liste" rausgeholt und von einem freien Thread (der wartet) verarbeitet, ob nun ein Thread nur einen oder mehrere "Listeneinträge" abarbeitet weiß ich noch nicht. Nun aber geht es nur um einige (erstmal 2-4 Threads) die so unabhängig wie möglich sind, um keine wartezeiten auszulösen (wie bei Mutex), dazu nutze ich Flags die ihn ihrer Nutzung aber sicher sind (insoweit das hier geklärte zutriff).
Dabei ging es mir in erster Linie natürlich darum, das es nicht zu Abstürzen oder fehlerhaften Ergebnissen kommt. Das sogar die Berechnung nacheinander ausgeführt wird, ist ein angenehmer Nebeneffekt, daß alles etwas einfacher macht, da man direkt nach dem setzen der Daten in einem Thread diese mit einem anderen auslesen kann ohne das die Daten vielleicht noch nicht "ganz berechnet" wurden.
Da ich gerade so einen Teil bearbeite nehme ich das also als Beispiel:
Da ich nun von vielen Clienten Daten empfange, diese in einen Buffer schreiben muß und dann ständig überprüfen muß was an Daten da sind um sie ab einem bestimmten Zeitpunkt zu bearbeiten, geht das nur sinnvoll mit Threads. Dabei schreibt z.B. ein Haupthread die Networkdaten in einen Speicherbereich, ein anderer Thread lies und überprüft diese und bei bedarf löscht er diese. Natürlich kann es dazu kommen, das wenn zwei Thread gleichzeitig auf diesen Bereich zugreifen, dies fehlschlägt, weil ein neuer Speicherbereich allokiert wurde.
Erstelle ich nun z.b. dafür immer wieder ein Mutex gibt es ähnliche Probleme wie beim erstellen von Threads, es dauert einfach so lang, das der ZEitgewinn durch die Threadverarbeitung mehrfach wieder dahin gerafft wird. Also muß ich es auf eine einfach und schnelle Weise machen und das geht mit einfachen Variablen (am besten in Strukturen) am besten.
NAtürlich gibt es mehrer, so wie bereits remi_meyer schrieb. Deshalb muß man auch dolle aufpassen, das man da die Struktur gut aufbaut, sonst hängt man selbst sein Programm unwiederbringlich auf. hehe. das macht so richtig Spaß so einen Mutexstrukturfehler zu finden.Das liest sich, als ob es mehrere Mutexe gibt, es gibt aber doch nur einen für alle Objekte, globalen Variablen usw.
Sonst müßte man ja bei der Erstellung des Mutex angeben, wofür er ist
1. Win10
PB6.1
PB6.1
-
Toshy
- Beiträge: 713
- Registriert: 22.03.2005 00:29
- Computerausstattung: Computer und Strom vorhanden
- Wohnort: LK Wolfenbüttel
@ts-soft
soweit ich weiß, weiß er nur eines "ich bin gemeint".
Beim erstellen des Mutex erhält man ja einen Wert, die MutexID, beim Sperren / Aufruf mit LockMutex(Mutex) muß man diese ID ja angeben. Jeder Thread der nun diese MutexID abfragt bleibt stehen, nur der erste Aufruf kommt durch. Es geht dann für den nächsten Thread erst weiter wenn der Erste ihn freigibt.
Erstellt man einen anderen Mutex mit einer anderen "ID", so werden Abfragen für diesen natürlich nur durchgeführt, wenn auch diese ID angegeben wird. Es gibt also mehrer unabhängige Mutex(mehrzahldinger;-)
Gruß
Toshy
soweit ich weiß, weiß er nur eines "ich bin gemeint".
Beim erstellen des Mutex erhält man ja einen Wert, die MutexID, beim Sperren / Aufruf mit LockMutex(Mutex) muß man diese ID ja angeben. Jeder Thread der nun diese MutexID abfragt bleibt stehen, nur der erste Aufruf kommt durch. Es geht dann für den nächsten Thread erst weiter wenn der Erste ihn freigibt.
Erstellt man einen anderen Mutex mit einer anderen "ID", so werden Abfragen für diesen natürlich nur durchgeführt, wenn auch diese ID angegeben wird. Es gibt also mehrer unabhängige Mutex(mehrzahldinger;-)
Gruß
Toshy
Zuletzt geändert von Toshy am 25.01.2007 15:48, insgesamt 1-mal geändert.
1. Win10
PB6.1
PB6.1
-
Kaeru Gaman
- Beiträge: 17389
- Registriert: 10.11.2004 03:22
also.. noch mal weiter rumgetestet...
das hauptproblem ist die auslastung.
eigentlich kein wunder, dass wenig CPU zur verfügung steht,
um die schleife im Hauptprogramm zu verarbeiten,
wenn schon x threads laufen, die die CPU unter Volllast setzen.
wie man sieht, hat das starten der threads ne halbe stunde gebraucht.
mit einer winzigen veränderung
sieht das schon ganz anders aus:
sogar mit Delay(0) geht der aufwand auf 1/20 sec runter,
mit Delay(1) ist die zeitangabe dann 0
also eindeutig:
das problem besteht dann, wenn mehrere threads auf Volllast laufen wollen.
@Toshy
bau also am besten in zeitintensive schleifen ein Delay(0) ein,
damit sich deine threads nicht gegenseitig zu sehr bremsen.
das hauptproblem ist die auslastung.
eigentlich kein wunder, dass wenig CPU zur verfügung steht,
um die schleife im Hauptprogramm zu verarbeiten,
wenn schon x threads laufen, die die CPU unter Volllast setzen.
Code: Alles auswählen
Label 1
starting No. 0
starting No. 1
starting No. 2
...
starting No. 99
1811250
Label 2
Label 3
Label 4
-1600444093mit einer winzigen veränderung
Code: Alles auswählen
Procedure Thread(dummy.l)
Repeat
glob + 1
Delay(0)
ForEver
EndProcedure Code: Alles auswählen
Label 1
starting No. 0
starting No. 1
starting No. 2
...
starting No. 99
47
Label 2
Label 3
Label 4
8756447mit Delay(1) ist die zeitangabe dann 0
also eindeutig:
das problem besteht dann, wenn mehrere threads auf Volllast laufen wollen.
@Toshy
bau also am besten in zeitintensive schleifen ein Delay(0) ein,
damit sich deine threads nicht gegenseitig zu sehr bremsen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Der Weise weiß, dass er ein Narr ist.
- remi_meier
- Beiträge: 1078
- Registriert: 29.08.2004 20:11
- Wohnort: Schweiz
Vielleicht ist es so einfacher zu verstehen:
Wenn man ein Objekt schützen möchte, erstellt man für dieses Objekt
eine CriticalSection. Will man nun Zugriff auf dieses Objekt erhalten,
betritt man diese Critical Section (EnterCriticalSection_() bzw. LockMutex()).
Man ist nun der einzige Thread in dieser CS und kann mit dem geschützten
Objekt alles machen, was man will. Dann verlässt man diese CS wieder.
Natürlich kann man so viele CS machen, wie man will. Eine CS stellt einfach
sicher, dass man der einzige Thread in dieser CS ist.
Wenn man ein Objekt schützen will, darf man es einfach nur in einer
CS manipulieren. Ausserhalb einer CS wäre das Objekt ungeschützt und
mehrere Threads könnten gleichzeitig das Objekt manipulieren.
Code: Alles auswählen
Procedure.l MutexCreate()
Protected *p = AllocateMemory(SizeOf(CRITICAL_SECTION))
If *p
InitializeCriticalSection_(*p)
EndIf
ProcedureReturn *p
EndProcedure
Procedure MutexFree(Mutex.l)
If Mutex
DeleteCriticalSection_(Mutex)
FreeMemory(Mutex)
EndIf
EndProcedure
Procedure MutexLock(Mutex.l)
EnterCriticalSection_(Mutex)
EndProcedure
Procedure.l MutexTryLock(Mutex.l)
ProcedureReturn TryEnterCriticalSection_(Mutex)
EndProcedure
Procedure MutexUnLock(Mutex.l)
LeaveCriticalSection_(Mutex)
EndProcedureeine CriticalSection. Will man nun Zugriff auf dieses Objekt erhalten,
betritt man diese Critical Section (EnterCriticalSection_() bzw. LockMutex()).
Man ist nun der einzige Thread in dieser CS und kann mit dem geschützten
Objekt alles machen, was man will. Dann verlässt man diese CS wieder.
Natürlich kann man so viele CS machen, wie man will. Eine CS stellt einfach
sicher, dass man der einzige Thread in dieser CS ist.
Wenn man ein Objekt schützen will, darf man es einfach nur in einer
CS manipulieren. Ausserhalb einer CS wäre das Objekt ungeschützt und
mehrere Threads könnten gleichzeitig das Objekt manipulieren.