Variable als Flag zur Threadsicherheit

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
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

Beitrag von ts-soft »

AND51 hat geschrieben:SOmit muss ich ja jede Variable quasi zweimal anlegen?!
Nein, nur eine für das MutexObject. Mithilfe dieses Objects, lassen sich alle
Shared (Global) Vars schützen durch LockMutex.

Lokale Variablen sind dadurch geschützt das jeder Thread einen eigenen
Stack hat. Für Static Variablen möchte ich das aber nicht behaupten, die sind
IMHO ungeschützt.
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.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Der Threadsafe-Modus in den Compiler-Optionen ist nur wichtig für die
Stringbearbeitung. Dabei kann es sich aber auch um verschiedene Strings
handeln.
Das heißt wenn du in verschiedenen Threads gleichzeitig mit Strings
arbeitest, dann sorgt "Threadsafe" dafür, dass sich die Stringoperationen
nicht in die Quere kommen.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

und wie ist das jetzt mit globalen?

ich bin davon ausgegangen, dass gemeinsamer zugriff auf ne speicherstelle
sicher sein muss, schon seit einführung das ersten pentium.
wieso sollte da in PB irgendwas anders sein....

@ts

würde mich mal interessieren, wie und was du getestet hast.
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.

Code: Alles auswählen

Global glob 

Procedure test1(a)
  For n=0 To 999999999
    glob+1
  Next
EndProcedure

Procedure test2(a)
  For n=0 To 99999999
    glob+1
  Next
EndProcedure

Procedure test3(a)
  For n=0 To 9999999
    glob+1
  Next
EndProcedure

NR1 = CreateThread(@test1(), 0)
NR2 = CreateThread(@test2(), 0)
NR3 = CreateThread(@test3(), 0)
For n=0 To 999
  glob+1
Next
WaitThread(NR1)
Debug glob
klar, die ausführung dauert ne weile, und die CPU wird a bissel wärmer,
aber aufhängen tut sich das ding nich.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8807
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Der PureBasic-Compiler kann nur einen String gleichzeitig bearbeiten. Ich
versuche es in Stichworten zu erklären:

- Thread 1 bearbeitet einen String
- Windows wechselt zu Thread 2
- Thread 2 fängt an einen String zu bearbeiten
- die globalen Werte zur Stringbearbeitung in PB werden verändert
- Windows wechselt zu Thread 1
- Die Stringbearbeitung wird falsch abgeschlossen, weil Thread 2 gleichzeitig auf die Stringproceduren zugegriffen hat
- "PureBasic.exe hat einen Fehler verursacht..."

Hier mal ein Code, der nur mit Threadsafe funktioniert:

Code: Alles auswählen

Global s.s = "hallo", Quit.l = #False
Procedure Thread(dummy.l)
  Repeat
    If s = "hallo"
      s + " du da!"
    ElseIf Right(s, 7) = " du da!"
      s = Left(s, 5)
    EndIf
  Until Quit
EndProcedure

thread1 = CreateThread(@Thread(), 0)
thread2 = CreateThread(@Thread(), 0)

OpenConsole()

Repeat
  PrintN(s)
  Delay(100)
Until GetAsyncKeyState_(#VK_ESCAPE)

Quit = #True
WaitThread(thread1)
WaitThread(thread2)

CloseConsole()
Eigentlich sollte meinem Wissen zufolge der Fehler auch auftreten, wenn
zwei unterschiedliche Strings manipuliert werden, aber da ist nichts
passiert.
Um es selbst zu testen, einfach hinter "Procedure" noch ein "Protected s.s = "hallo""
einfügen.
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Beitrag von HeX0R »

ReadMe hat geschrieben: For global stuff, the rule is that access to the numeric types is atomic, this
means if thread A does "a = 512" and thread B does "a = 123" at the exact
same time, one is actually fully completed before the other is executed.
(the reason is that threads never switch between the simple asm instructions
like mov, add, push, pop, ...)
So you will end up with either 512 or 123 (depending of what came last), but
there will never be any mixup or something.

Basically everything that gets more complex than this (and is done on global things)
should be protected by a mutex.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

nu siehste woll?

....hab ich doch glei gesagt.
Toshy hat geschrieben:...Also kann es auch sein das Variable flag.b gleichzeitig von zwei Threads hochgezählt wird, da mache ich mit
b + 1 bzw. b - 1
Da ich ja nur einen kurzen Befehl nutze, dürfte es doch keine Probleme geben, oder?
...
Kaeru Gaman hat geschrieben:yup, kannst du sicher sein.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
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

Beitrag von ts-soft »

Code: Alles auswählen

Global glob.l

Dim Threads.l(99)

Procedure Thread(dummy.l)
  Repeat
    glob + 1
  ForEver
EndProcedure

For I = 0 To 99
  Threads(I) = CreateThread(@Thread(), 0)
Next

Delay(5000)

For I = 0 To 99
  KillThread(Threads(I))
Next

Debug glob
Bei mir hängt sich das meist auf, und es sind nur 100 Threads, wie ich
Toshy einschätze möchte er mehr erstellen <)
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.
Bild
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

ich glaube nicht, dass er sich wirklich aufhängt,
das problem liegt wohl eher daran, dass du dieselbe proc mehrfach threadest.

ich habs mal timer getestet.

zum starten von 10 threads braucht er fast 2 sekunden,
zum starten von 20 threads braucht er fast 15 sekunden,
zum starten von 21 threads braucht er fast 18 sekunden.
anscheinend steigt das exponentiell an,
also braucht er einfach sehr lange,
um deine 100 threads auf derselben proc zu starten.

Code: Alles auswählen

Global glob.l 

Dim Threads.l(99) 

#LastThread = 20

Procedure Thread(dummy.l) 
  Repeat 
    glob + 1 
  ForEver 
EndProcedure 

Debug "1"
time = ElapsedMilliseconds()
For I = 0 To #LastThread 
  Threads(I) = CreateThread(@Thread(), 0) 
Next 
time = ElapsedMilliseconds() - time
Debug time
Debug "2"
Delay(5000) 
Debug "3"
For I = 0 To #LastThread 
  KillThread(Threads(I)) 
Next 
Debug "4"
Debug glob
egal wie viele threads Toshy verwenden will,
er wird bestimmt nicht hunderte derselben einfachen endloszähler starten wollen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
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

Beitrag von ts-soft »

>> das problem liegt wohl eher daran, dass du dieselbe proc mehrfach threadest.
Sonst machts doch keinen Spaß :lol:
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.
Bild
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

habs mal mit 10 identischen procs getestet, macht keinen unterschied.

wieauchimmer, ich finde, wilde spekulazius bringen nix....

es wäre erstmal interessant zu wissen, was Toshy im grunde vorhat.
aber was auch immer das ist, ich bezweifle einfach mal,
dass es eine ähnlichkeit mit dieser extremen versuchsanordnung hat.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten