Seite 1 von 2

semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 00:29
von Toshy
Hilfedatei:
Anders als ein Mutex ist ein Semaphore-Objekt nicht "im Besitz" eines bestimmten Threads, was bedeutet dass Signal/Warte-Aufrufe nicht vom gleichen Thread erfolgen müssen, wie dies mit LockMutex() und UnlockMutex() der Fall ist.
Verstehe ich nicht, mache ich was falsch oder PB oder erklärt es die Hilfe wieder nicht so richtig? Ich überlege jetzt zum ersten mal Semaphore wirklich zu nutzen. Aber ich merke, das mir mutex eventuell doch eher paßt.
Was ich nämlich nicht wußte, das mutex intern auch einen zähler hat.
so kann ich lockmutex() in einem thread mehrfach aufrufen OHNE unlock() aufzurufen und OHNE das der thread sich selbst blockiert.
LockMutex(mutex)
LockMutex(mutex)
blockeriert NICHT.
Um aber den Zugriff einem anderen Thread zu gestatten, reicht nicht nur EIN unlock(), sondern es muß so oft kommen, wie auch lockmutex() aufgerufen wurde. Das hat mich doch ein wenig erstaunt. An sich ja unwichtig wenn man sauber programmiert.
WICHTIG:
Was ich aber gar nicht wußte und nie getestet habe und ich wohl auch nie einen unlockfehler hatte um es zu bemerken ist, daß man einen das Unlock aus jedem thread aufrufen kann. ruft Beispielweise Thread2 zwei mal lockmutex(mutex) auf und ruft DANACH Thread1 ebenfalls lockmutex(mutex) auf, so blockiert Thread 1 natürlich. jetzt ruft Thread3 einfach zwei mal unlock(mutex) auf und schon läuft thread1 weiter.
Ist das Absicht (normal) oder ein Fehler?
Weil ich das an sich echt super finde. Leider steht das so nicht in der Hilfe und ich habe es daher nicht genutzt.

Code: Alles auswählen

Global mutex = CreateMutex()
Procedure thread1(dummy)
  
  Repeat
  LockMutex(mutex)  
  Debug "thread1"
  UnlockMutex(mutex)
  Delay(1000)
  ForEver
EndProcedure
Procedure thread2(dummy)
  LockMutex(mutex)
  LockMutex(mutex)
  LockMutex(mutex)
  TryLockMutex(mutex)
  TryLockMutex(mutex)
  Repeat
  Debug "thread2"
  Delay(1000)
  ForEver
EndProcedure
Procedure thread3(dummy)
  UnlockMutex(mutex)
  UnlockMutex(mutex)
  UnlockMutex(mutex)
  UnlockMutex(mutex)
  UnlockMutex(mutex)
  Repeat
  Debug "thread3"
  Delay(1000)
  ForEver
EndProcedure

CreateThread(@thread1(), 0)
Delay(4000)
CreateThread(@thread2(), 0)
Delay(4000)
CreateThread(@thread3(), 0)


Repeat
  
  Delay(3000)
  ForEver
mutex() scheint somit genau so zu arbeiten wie semaphore() mit dem Unterschied, das man keinen Anfangswert angeben kann und so beim "runterzählen" mit lockmutex() nur ein Thread weiter laufen kann. wie das mit trymutex ist muß ich jetzt noch testen.

Wenn das korrekt ist, bin ich ja hooooooch erfreut (und ärgerlich, das ich das nicht schon immer wußte)

Gruß
toshy

NAchtrag:
Trylockmutex() funktioniert genau so.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 00:56
von STARGÅTE
Toshy hat geschrieben:so kann ich lockmutex() in einem thread mehrfach aufrufen OHNE unlock() aufzurufen und OHNE das der thread sich selbst blockiert.

Zitat:
LockMutex(mutex)
LockMutex(mutex)

blockeriert NICHT.
Um aber den Zugriff einem anderen Thread zu gestatten, reicht nicht nur EIN unlock(), sondern es muß so oft kommen, wie auch lockmutex() aufgerufen wurde. Das hat mich doch ein wenig erstaunt. An sich ja unwichtig wenn man sauber programmiert.
Dieses Verhalten ist vollkommen richtig.

Wenn man zB eine Prozedur schreibt (in der irgendwas wichtiges Passiert) und in der einen Lock/Unlock Block hat, so möchte man diese Prozedur natürlich von verschiedenen Orten aufrufen können, u.a. auch innerhalb einen anderen Lock/Unlock Blocks.
Somit ist es normal (und auch richtig) das Locks im selben Thread sich nicht blockieren und das auch genauso viele Unlocks wie Locks innerhalb des selben Threads aufgerufen werden.

Dein anderen Beispiel, indem es keine richtigen Blöcke gibt, geht an der Funktionsweise ehr vorbei.
Zumindest wird ja im normalfall kein Unlock ohne eigenem Lock aufgerufen.
Da es nicht offiziell dokumentiert ist, würde ich mich auch nicht darauf verlassen, dass es in späteren Versionen auch noch so ist.
Wenn du wirklich ein Hersteller/Konsument-System machen willst, solltest du dafür auch Semaphores nutzen und nicht Threads.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 02:56
von Toshy
solltest du dafür auch Semaphores nutzen und nicht Threads
Du meinst sicher "mutex" nicht "Threads" ;-)

Ich nutze seit vorhin auch zur Sicherheit semaphore. funktioniet in meinem code aber beides gleich.
Nur weil wieder mal etwas in der Hilfe steht, aber anders funktioniert wollte ich mal wissen was drann ist.
Na ja, dann nehme ich für einige wenige Dinge mal semaphore. Undokumentiertes nehme ich nur im Notfall.
Ich hatte nur gedacht, daß dies vielleicht auch eine offizielle Funktion der Mutex ist. Im Internet hatte ich nicht viel dazu gefunden, außer das "Mutex" kein wirklich fester Begriff für genau eine Art der Funktion ist. bewirken (beim programmieren) immer das selbe, aber wohl schon mal auf die oder jene art.

na gut, wenn jemand doch noch dem Interesse halber etwas dazu weiß, immer her mit eurem Wissen. An sonsten denke ich, ist da hier erledigt.

Danke.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 03:31
von STARGÅTE
Ich muss mal nachhaken:
Eigentlich kann man die beiden Sachen (Semaphores und Mutex) doch garnnicht "gleichsetzen".

Semaphores "sperren" doch die meiste Zeit eine aktion, bis es ein Signal gibt, sodass etwas passieren darf.
Wobei Semaphores auch quantitativ arbeiten und nicht nur quallitativ.
Mutex machen genau das Gegenteil, sie sind meist "offen" und sperre nur dann, wenn eine aktion nicht mit anderen zusammen laufen darf.

Wenn du also ein Mutex als Semaphores nutzen würdest, müsstest du zu Anfang min. einmal Lock aufrufen, und dann immer Unlock/Lock, statt Lock/Unlock.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 21:09
von freak
Die Hilfe ist eigentlich ziemlich klar:
Hinweis: Ein Mutex kann nur durch den Thread entsperrt werden, welcher ihn auch gesperrt hat.
http://www.purebasic.com/german/documen ... mutex.html

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 22:44
von Toshy
hehe. grins. genau das steht da. das weiß ich und deshalb der Beitrag.
Es stimmt "tatsächlich" nur nicht.
Die Hilfe ist hier wie an einigen anderen Stellen falsch oder ungenau.
Den Hinweis muß man ändern oder weg lassen.

Man kann auch aus anderen Threads einen Mutex entsperren.

Aufgefallen war es mir zu ersts, weil ich in einem anderen thread versehentlich einen falschen "Mutexnamen" zum freigeben eingab. waren nur 3 buchstaben anders. und ups... anderer thread wurde entsperrt. allerdings war das auffinden nicht einfach, denn damit hatte ich halt nicht gerechnet.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 23:17
von STARGÅTE
Man kann auch aus anderen Threads einen Mutex entsperren.
An dieser Stelle muss ich Toshy recht geben.

Das heißt, Thread 1 kann ein Mutex sperren und Thread 2 ihn wieder freigeben.

Hier mal in kurzer Ausführung:

Code: Alles auswählen

Global Mutex = CreateMutex()

Procedure Thread1(Null)
	Delay(2000)
	LockMutex(Mutex)
	Debug "Thread 1 hat Mutex gesperrt"
EndProcedure

Procedure Thread2(Null)
	Delay(4000)
	UnlockMutex(Mutex)
	Debug "Thread 2 : Mutex entsperrt"
EndProcedure

Procedure TestThread(Null)
	Repeat
		Delay(250)
		If TryLockMutex(Mutex)
			Debug "TestThread : Mutex offen"
			UnlockMutex(Mutex)
		Else
			Debug "TestThread : Mutex gesperrt"
		EndIf
	ForEver
EndProcedure

CreateThread(@TestThread(), #Null)
CreateThread(@Thread1(), #Null)
CreateThread(@Thread2(), #Null)

Delay(6000)
Man kann also durchaus, Thread-übergreifend sperren und entsperren.
Es ist aber, wie ich schon andeutete, nicht sinn der Sache und vermutlich nicht beabsichtigt.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 10.06.2012 23:24
von freak
Der Hinweis steht da nicht ohne Grund. Nur weil es bei euch nicht zum Fehler kommt heißt noch lange nicht das diese Art der Benutzung garantiert funktioniert. Oder kann euer kleines Testprogramm beweisen, dass diese Art der Benutzung sicher ist auf jedem Syetem und in jeder Situation?

hehe. grins.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 11.06.2012 00:34
von Toshy
Nein, kann es nicht, aber darum geht es auch nicht.
Mir geht bzw. ging es ja daraum rauszufinden ob die Hilfe korrekt ist oder nicht.
So wie bzw. hin und wieder Funktionen noch richtig oder vollständig beschrieben wurden.
Aktuell is es ja immer noch bei einigen Networkdingen so daß die Hilfe dort einfach falsch oder nicht ganz vollständig beschreibt.

Seit ich daß weiß, nutze ich die Funktionen natürlich anders.
Und hier hätte das ja auch so sein können oder ist vielleicht so.
Da man hier aber noch die Semaphore hat, ist man nicht dazu gezwungen die undokumentierte weiße absichtlich zu nutzen. Dennoch dürfte in der Hilfe dann nicht stehen, was nciht stimmt.
Ich werde die Tage da mal eine Richtigstellung des Textes erbeten.

Re: semaphore() vs. mutex() - mutex hat auch Zähler

Verfasst: 11.06.2012 00:59
von NicTheQuick
Unter Linux funktioniert das nicht, wie die Ausgabe von Stargates Code beweist:

Code: Alles auswählen

TestThread : Mutex offen
TestThread : Mutex offen
TestThread : Mutex offen
TestThread : Mutex offen
TestThread : Mutex offen
TestThread : Mutex offen
TestThread : Mutex offen
TestThread : Mutex offen
Thread 1 hat Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
Thread 2 : Mutex entsperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
TestThread : Mutex gesperrt
Und genau so sollte es auch sein. Dass Windows das nicht richtig macht, ist wohl ein Fehler in Windows. Auch Java lässt es nicht zu einen Lock aus einem anderen Thread heraus wieder zu entsperren.

Die Hilfe stimmt also. Man könnte höchstens noch einen Hinweis dazu schreiben, dass es sich unter Windows möglicherweise anders verhält. Aber was will man mit einer solch schwammigen Aussage?