Seite 1 von 2
[definitiv Bug] TryLockMutex(Mutex) und LockMutex(Mutex)
Verfasst: 05.02.2006 23:35
von Toshy
[edit]Bugmeldung für Freak im achten Beitrag (06 Feb 2006 21:56:41)
[/edit]
Hi,
wie soll den TryLockMutex(Mutex) genau funktionieren, habe das wohl nicht ganz verstanden und wie soll sich darauf dann LockMutex(Mutex) verhalten.
TryLockMutex(Mutex) soll doch wenn vorhanden den mutex "verriegeln".
Das tut es zwar wohl auch, aber es liefert IMMER nur NULL zurück, das sollte denke ich nicht sein, oder? "otherwise" steht da doch.
Die Funktion TryLockMutex(Mutex) an sich ist sehr sinnvoll, vor allem in kombination mit LockMutex(Mutex), aber damit funktioniert es nicht so richtig bzw. sinnvoll. zwar verriegelt TryLockMutex(Mutex) den codeteil dann für "LockMutex(Mutex)", aber umgekehrt (leider) nicht. das TryLockMutex(Mutex) verriegelt kann ja nur sinnvoll sein, wenn "lockmutex" nicht gleichzeitig mit einem TryLockMutex(Mutex) laufen darf. aber das passiert ja doch, denn wenn lockmutex verriegelt gilt dies leider nicht für TryLockMutex(Mutex).
TryLockMutex(Mutex) liefert bei mir auch immer nur NULL zurück und daher weiß ich leider nicht wie ich beides "vernüpftig" nutzen kann.
kann mir da mal jemand ein bissl was erklären.
ich brauche dies nämlich für einige Critical Sektions, aber für 3 Arten.
1. Nur ein Thread darf den Codeteil nutzen, alle anderen warten.
2. Nur ein Thread darf den Code nutzen, alle anderen warten aber nicht sondern gehen mit einem Rückgabewert weiter so daß ich den codeteil überspringen kann.
3. Alle Threads dürfen den Codeteil gleichzeitig nutzen, außer wenn einer dies nicht zuläßt, dieser wartet dann und verriegelt die anderen.
1. ist das einfach lockmutex
aber wie bekomme ich das andere hin? mit TryLockMutex(Mutex) klappt es nicht korrekt soweit ich bisher getestet habe. probiere es seit gestern, aber mache jetzt gleich mal weiter, vielleicht komme ich ja noch drauf.
bin also für Tips dankbar.
Gruß
Toshy
Verfasst: 06.02.2006 15:44
von remi_meier
Kleiner Beispielcode:
Code: Alles auswählen
enableexplicit
Global Dim names.s(3)
Global NewList queue.s()
Global counter.l, mutex.l
names(0) = "peter"
names(1) = "hans"
names(2) = "franz"
names(3) = "juuli"
mutex = CreateMutex()
Procedure thread(index.l)
Protected name.s, z.l
name = names(index)
z = 0
Repeat
LockMutex(mutex)
counter + 1
AddElement(queue())
queue() = name
UnlockMutex(mutex)
Delay(Random(500) + 200)
z + 1
Until z = 20
EndProcedure
Define.l t
t = CreateThread(@thread(), 0)
t = CreateThread(@thread(), 1)
t = CreateThread(@thread(), 2)
t = CreateThread(@thread(), 3)
Repeat
LockMutex(mutex)
ForEach queue()
Debug queue()
DeleteElement(queue())
Next
UnlockMutex(mutex)
Delay(50)
Until counter = 80
FreeMutex(mutex)
TryLockMutex() wird z. B. so verwendet (ausm Kopf):
Code: Alles auswählen
; im Thread:
changed = #false
repeat
If TryLockMutex(mutex)
; änder das was du ändern willst
changed = #true
else
; mach was solange die ressource gebraucht wird -> Wird nicht unter-
; brochen mit LockMutex()
EndIf
until changed
Verfasst: 06.02.2006 16:53
von remi_meier
Hatte grad etwas Zeit:
Code: Alles auswählen
Global mutex.l
mutex = CreateMutex()
Procedure test(dummy.l)
Delay(500)
Protected changed.l
changed = #False
Repeat
If TryLockMutex(mutex)
Debug "Endlich durchgekommen!"
changed = #True
UnLockMutex(mutex)
Else
Delay(100)
Debug "Mann! Du blockst mich"
EndIf
Until changed
EndProcedure
t = CreateThread(@test(), 5)
LockMutex(mutex)
Delay(1000)
; eine Sekunde lang blocken
UnlockMutex(mutex)
WaitThread(t)
FreeMutex(mutex)
Debug "Ende!"
greetz
Remi
edit: nach Freak ausgebessert!
Verfasst: 06.02.2006 17:01
von freak
LockMutex() wartet bis der Mutex frei ist.
TryLockMutex() wartet nicht, sondern gibt 0 zurück wenn der Mutex nicht frei war.
remi_meier:
Nach einem erfolgreichen TryLockMutex() muss auch ein UnlockMutex() stehen,
sonst bleibt er immer im "locked" status. (ist in dem Beispiel egal, sonst aber ungemein wichtig.)
Verfasst: 06.02.2006 17:09
von remi_meier
Stimmt, sry, war wohl ein wenig unvorsichtig... hab noch ein FreeMutex()
hinzugefügt

Verfasst: 06.02.2006 18:30
von Toshy
TryLockMutex() wird z. B. so verwendet (ausm Kopf):
Code:
; im Thread:
changed = #false
repeat
If TryLockMutex(mutex)
; änder das was du ändern willst
changed = #true
else
; mach was solange die ressource gebraucht wird -> Wird nicht unter-
; brochen mit LockMutex()
EndIf
until changed
Ich hatte gestern noch was getest und zwar, war ich beim testen sehr verwirrt und sehe jetzt klarer. Leider scheint das NICHT zu stimmen was du schreibst. Ich dachte auch das dies so sein soll, aber es ist so das Try.. auch STARTET wenn der code vom normalen LOCK ausgeführt wird. Der unterschied ist, es wird beim aufruf vom Try der normale "lock-thread-code" GESTOPPT. das ist ja an sich toll, hilft aber in den meißten fällen nicht. zwar kann so nicht doppelt etwas beschrieben werden, aber stellt man sich für, thread A beschreibt eine einen listeneintrag (mehrere felder), er wird gestoppt und dann wird dieser eintrag gelöscht. was dann? also es ist nicht so, das der "Try-Code" erst dann ausgeführt wird, wenn der normale code AM ANFANG gestoppt wurde, oder wenn er abgearbeitet wird, sondern SOFORT (mit stoppen des anderen threads).
Das kann so Katastrophen führen und die Funktion wohl in den meißten Fällen nicht zu bebrauchen. Auf jedenfall bei mir in keinem einzigen Fall.
auf jedenfall sah es bisher so aus.
Ist natürlich schwer sowas zu testen
Aber auf Grund eurer Infos teste ich mal, denn ich kann mich ja total irren.
......
so, ne ganze Testzeit später.
....
ich könnte jetzt den Text oben weglöschen, aber so sieht man wie ich es gedacht hatte. Das lag wohl am schlechten Englisch meinerseits wie aber auch an meiner eigenen CSsektun die halt etwas anders arbeitet.
Ich werde zwar jetzt erst recht testen müssen, aber schön zu wissen wie es gemeint ist.
Daher zum voräufigen Abschluß also noch wichtige Punkte:
1. Ich habe mich also total geirrt in der Auffassung der Funktion Try...
2. Großes Danke an euch
Gruß
Toshy
Verfasst: 06.02.2006 22:25
von Toshy
@remi_meier
Also da habe ich mich doch zu früh gefreut. von euer erklärung und dem beispiel klang alles super, aber es klappt nicht.
beim beispiel kommt minuten lang (auch ganz zu anfang) nur
"Mann! Du blockst mich"
Trylock ist IMMER null.
auch mal nur zum test
m = CreateMutex()
Debug m
Ergebnis = TryLockMutex(m)
Debug Ergebnis
ist immer null bei mir.
[edit]ich meine deinen Zweiten code, den ersten noch nicht getest.
aber Try gibt bisher bei mir halt IMMER NULL zurück.
Bin ich jetzt blöd oder was?
Verfasst: 06.02.2006 22:56
von Toshy
Hallo.
Ich bin mir sicher, das ist ein Bug.
Ich dachte ich bin blöd, aber dem ist wohl doch nicht so.
Code: Alles auswählen
OpenConsole()
Global mutex.l
mutex = CreateMutex()
Procedure test(dummy.l)
Delay(500)
Protected changed.l
changed = #False
Repeat
If TryLockMutex(mutex)
PrintN( "Endlich durchgekommen!" )
changed = #True
UnlockMutex(mutex)
Else
Delay(100)
PrintN( "Mann! Du blockst mich" )
EndIf
Until changed
EndProcedure
t = CreateThread(@test(), 5)
LockMutex(mutex)
Delay(1000)
; eine Sekunde lang blocken
UnlockMutex(mutex)
WaitThread(t)
FreeMutex(mutex)
Delay(15000)
Debug "Ende!"
CloseConsole()
Ich habe mal zum testen, weil mir hier einiges sehr komisch war diesen Code zur EXE kompiliert und auf meinem Windows XP Rechner laufen lausen. Und oh wunder, der Code läuft, Trylockmutex() funktioniert.
Aber auf meinem Windows 98 Rechner geht es NICHT (kein SE).
Bei Windows 98 funktioniert trylockmutex nicht.
Wie kann das denn sein?
Gruß
Thorsten
[edit]
ach ja, ich weiß natürlich nicht, ob es am unterschiedlichen betriebssytem liegt oder das der Rechner auf dem es geht einen AMD 2400XP besitzt und auf dem es nicht geht ein AMD 1800XP CPU ist.
Verfasst: 07.02.2006 00:26
von Toshy
Bestätigt. Die selbe EXE von mir hat bei einem Freund (Intel CPU`S) auf dem Windows XP funktioniert und auf einem Windows 98SE nicht.
Auf Windows98 und SE geht trylockmutex nicht.
Wann kommt vermutlich die nächste Beta?
Verfasst: 07.02.2006 00:30
von MLK
habe mich vorhin schon gewundert, denn bei mir (win2000) läufts auch
