Mutext?

BlitzMax Forums/BlitzMax Beginners Area/Mutext?

Yue(Posted 2016) [#1]
I 'm trying to understand the mutex , but I do not succeed, I do not see the difference in the console about it.

Any suggestions ?

SuperStrict

Global Mutex:TMutex  = CreateMutex() 'create the mutex.  This mutex will be locked anytime a thread needs access to the consol

Function Hello:Object(data:Object)
	'LockMutex(Mutex) 'Lock the mutex so we can have exclusive access to the consol
	Print "Hello 1"
	Print "Hello 2"
	Print "Hello 3"
	Print "Hello 4"
	Print "Hello 5"
	Print "Hello 6"
	'UnlockMutex(mutex) 'unlock the mutex to allow other threads access
End Function

Function GoodBye:Object(data:Object)
	'LockMutex(Mutex) 'lock the mutex blah blah
	Print "Good bye 1"
	Print "Good bye 2"
	Print "Good bye 3"
	Print "Good bye 4"
	Print "Good bye 5"
	Print "Good bye 6"
	'UnlockMutex(Mutex) 'blah again
End Function
CreateThread(Hello,Null)
CreateThread(GoodBye,Null)

Delay(1000) 'delay to allow threads to finish




Derron(Posted 2016) [#2]
There is nothing happening because it finishes printing "too fast"

SuperStrict
Framework Brl.StandardIO 'for print
Import Brl.Threads 'for mutex


Global Mutex:TMutex  = CreateMutex() 'create the mutex.  This mutex will be locked anytime a thread needs access to the consol

Function Hello:Object(data:Object)
	'LockMutex(Mutex) 'Lock the mutex so we can have exclusive access to the consol
	For local i:int = 0 to 10
		Print "Hello Hello Hello Hello Hello" + i
	Next
	'UnlockMutex(mutex) 'unlock the mutex to allow other threads access
End Function

Function GoodBye:Object(data:Object)
	'LockMutex(Mutex) 'lock the mutex blah blah
	For local i:int = 0 to 10
		Print "Bye Bye Bye Bye Bye Bye Bye Bye" + i
	Next
	'UnlockMutex(Mutex) 'blah again
End Function
CreateThread(Hello,Null)
CreateThread(GoodBye,Null)

Delay(1000) 'delay to allow threads to finish



Mutexes disabled. See how both threads break the output of the other thread?
Hello Hello Hello Hello Hello0
HBello Hyeel Blyoe  BHye Byee lBlyoe  Bye BHye Byee0
l
lo Bye Bye Bye Bye Bye Bye Bye Bye1
Bye Bye Bye Bye Bye Bye Bye Bye2
Bye Bye Bye Hello1Bye Bye
BHello Hello Helyel oBye Bye3 Hello He
ll
Bye Bye Bye Bye Bye Bye Bye Bye4
Bye Bye Byeo2
Hello Hello Hello Bye Bye  Bye HByee Byle5l
Bye Bye Bye Bye Bye Bye Bye Bye6
Byo Hello3
e By
e HelloBye B ye HBeyel Bye lBye Boye7
HBye Bye Bye Bye Bye Bye Bye Bye8
eBye Bye Blye Byle Bye oBy e ByeH Byee9
lBye Bye lBye oBye  Bye Bye BHye Beye10
llo4
Hello Hello Hello Hello Hello5
Hello Hello Hello Hello Hello6
Hello Hello Hello Hello Hello7
Hello Hello Hello Hello Hello8
Hello Hello Hello Hello Hello9
Hello Hello Hello Hello Hello10



And this happens when enabling the mutexes:
Hello Hello Hello Hello Hello0
Hello Hello Hello Hello Hello1
Hello Hello Hello Hello Hello2
Hello Hello Hello Hello Hello3
Hello Hello Hello Hello Hello4
Hello Hello Hello Hello Hello5
Hello Hello Hello Hello Hello6
Hello Hello Hello Hello Hello7
Hello Hello Hello Hello Hello8
Hello Hello Hello Hello Hello9
Hello Hello Hello Hello Hello10
Bye Bye Bye Bye Bye Bye Bye Bye0
Bye Bye Bye Bye Bye Bye Bye Bye1
Bye Bye Bye Bye Bye Bye Bye Bye2
Bye Bye Bye Bye Bye Bye Bye Bye3
Bye Bye Bye Bye Bye Bye Bye Bye4
Bye Bye Bye Bye Bye Bye Bye Bye5
Bye Bye Bye Bye Bye Bye Bye Bye6
Bye Bye Bye Bye Bye Bye Bye Bye7
Bye Bye Bye Bye Bye Bye Bye Bye8
Bye Bye Bye Bye Bye Bye Bye Bye9
Bye Bye Bye Bye Bye Bye Bye Bye10



There are many chances it "with pure luck" works without Mutexes - but there is no guarantee. So best is to use these mutexes for such scenarios.


bye
Ron


Yue(Posted 2016) [#3]
Here disable Mutex.
Building Inicio
Compiling:Inicio.bmx
flat assembler  version 1.69.14  (1819004 kilobytes memory)
3 passes, 2634 bytes.
Linking:Inicio.debug.mt.exe
Executing:Inicio.debug.mt.exe
Hello Hello Hello Hello Hello0
Hello Hello Hello Hello Hello1
Hello Hello Hello Hello Hello2
Hello Hello Hello Hello Hello3
Hello Hello Hello Hello Hello4
Hello Hello Hello Hello Hello5
Hello Hello Hello Hello Hello6
Hello Hello Hello Hello Hello7
Hello Hello Hello Hello Hello8
Hello Hello Hello Hello Hello9
Hello Hello Hello Hello Hello10
Bye Bye Bye Bye Bye Bye Bye Bye0
Bye Bye Bye Bye Bye Bye Bye Bye1
Bye Bye Bye Bye Bye Bye Bye Bye2
Bye Bye Bye Bye Bye Bye Bye Bye3
Bye Bye Bye Bye Bye Bye Bye Bye4
Bye Bye Bye Bye Bye Bye Bye Bye5
Bye Bye Bye Bye Bye Bye Bye Bye6
Bye Bye Bye Bye Bye Bye Bye Bye7
Bye Bye Bye Bye Bye Bye Bye Bye8
Bye Bye Bye Bye Bye Bye Bye Bye9
Bye Bye Bye Bye Bye Bye Bye Bye10

Process complete


Enable Mutex.
Building Inicio
Compiling:Inicio.bmx
flat assembler  version 1.69.14  (1814975 kilobytes memory)
3 passes, 3080 bytes.
Linking:Inicio.debug.mt.exe
Executing:Inicio.debug.mt.exe
Hello Hello Hello Hello Hello0
Hello Hello Hello Hello Hello1
Hello Hello Hello Hello Hello2
Hello Hello Hello Hello Hello3
Hello Hello Hello Hello Hello4
Hello Hello Hello Hello Hello5
Hello Hello Hello Hello Hello6
Hello Hello Hello Hello Hello7
Hello Hello Hello Hello Hello8
Hello Hello Hello Hello Hello9
Hello Hello Hello Hello Hello10
Bye Bye Bye Bye Bye Bye Bye Bye0
Bye Bye Bye Bye Bye Bye Bye Bye1
Bye Bye Bye Bye Bye Bye Bye Bye2
Bye Bye Bye Bye Bye Bye Bye Bye3
Bye Bye Bye Bye Bye Bye Bye Bye4
Bye Bye Bye Bye Bye Bye Bye Bye5
Bye Bye Bye Bye Bye Bye Bye Bye6
Bye Bye Bye Bye Bye Bye Bye Bye7
Bye Bye Bye Bye Bye Bye Bye Bye8
Bye Bye Bye Bye Bye Bye Bye Bye9
Bye Bye Bye Bye Bye Bye Bye Bye10

Process complete



I am confused.


Yue(Posted 2016) [#4]
Ok, no problem, I was looking at the output of the debugger, but the executable and msdos window you can see the difference. Thanks You. =)




Yue(Posted 2016) [#5]
Ok, I will try to explain what they have learned if I touched taught; arle to someone else.

The mutex is like what I have on my TV where if I press down drastically the volume of the TV.

So the threads are like every person who pulls in a room, for example, if two people speak at the same time do not understand anything, so when a person listens to the other, that's mutex, and when he begins to speak the otre person enters mutex.

=) I'm right?


Floyd(Posted 2016) [#6]
A more computing oriented example:

Two processes may change a certain value, perhaps the amount of money in an account.
Let's say the value is now 10, and each process tries to add 1.

If they operate in sequence then one process will read the value 10, add 1 to get 11 and write that new value.
The other process will read 11, add 1 and write 12.

But if they can operate in any uncontrolled order we may have

First process reads a 10.
Second process reads a 10.
Each process adds 1 to get 11.
Each process writes 11 as new value.

So the end result is 11 when it should be 12.

There must be some mechanism by which a process declares that it will access the value. Everyone else is then excluded from doing the same until the first process is finished and declares it is done.

That is mutual exclusion.


Floyd(Posted 2016) [#7]
One more comment.

This can be very hard to debug. In the example I just gave there is an error only when there is conflict between two processes operating at almost exactly the same time. The program might run flawlessly the first thousand times and then suddenly fail.


Yue(Posted 2016) [#8]
thanks Floyd,
A simple example of semaphore ?


Derron(Posted 2016) [#9]
Google "BlitzMax semaphore":
https://en.wikibooks.org/wiki/BlitzMax/Modules/System/Threads#CreateSemaphore



bye
Ron


Yue(Posted 2016) [#10]
Thanks you Derron.

This really is very confusing to me, I'm reading some articles that talk about a public restroom where a single user can use it, for mutex, then I read another article about philosophers eating at a table with some forks, where if you have a fork can eat and the other has to wait where in the end one can starve. So my brain is trying to absorb all this in the best way possible.


Or other item of a barber , the barber's chair and chairs waiting for customers. this is crazy.


col(Posted 2016) [#11]
Semaphores...

I find some examples with multithreading are difficult to understand too.

Simple explanation - a semaphore is a value than can make a thread wait when its value is 0 when any thread calls WaitSemaphore. If the value is non zero and WaitSemaphore is called then the value is decremented -1 and the thread continues. If a PostSemaphore is used the value is incremented +1 and the thread will always continue. That's *all* it does.

Same explanation...
Start it with a value, any positive value. Every time you call PostSemaphore then the value will increment +1. Everytime you call WaitSemaphore then the value will decrement -1. When the value gets to zero and a WaitSemaphore is called then WaitSemaphore will wait until the value is more than 0 and will then decrement again. Now to know any thread can safely call WaitSemaphore and Postsemaphore without any problem with updating its value.


EDITED:-
Some examples to help understand, use the Debugger to step through the code and you can see where the thread is forced to wait. You will need to exit via the editors debug STOP icon when the program enters a wait state.
' create a semaphore with a value of 2
Local sem:TSemaphore = CreateSemaphore(2)

DebugStop
WaitSemaphore sem ' sem value is now 1 and the thread continues
WaitSemaphore sem ' sem value is now 0 and the thread continues

' The thread will wait at the next WaitSemaphore because the sem value was 0 previously. This thread will wait until another thread 'PostSemaphore sem' to make the sem value +1.
WaitSemaphore sem

' this next line cannot be reached until another thread PostSemaphore sem! There are no other threads so we need to exit via the editor debugger icons
Local oops:Int




Another example with single thread
' Try this example and step through

' create a semaphore with a value of 2
Local sem:TSemaphore = CreateSemaphore(2)

DebugStop
WaitSemaphore sem ' sem value is now 1 and the thread continues
PostSemaphore sem ' sem value is now 2 and the thread continues
WaitSemaphore sem ' sem value is now 1 and the thread continues
WaitSemaphore sem ' sem value is now 0 and the thread continues

' The debugger will stop at the next instruction because the sem value was 0 previously - youll need to exit the program via the Stop icon in the editor
WaitSemaphore sem

' this next line cannot be reached until another thread PostSemaphore! There are no other threads so we need to exit via the editor debugger icons
Local oops:Int


Now imagine that other threads can postsemaphore and waitsemaphore too.


Derron(Posted 2016) [#12]
A "real world example" of what col described is:

there is a bar, with a barkeeper filling glasses with beer. He fills one and starts with the next. Each time he filled a glass, the amount of glasses on the table increases ("PostSemaphore").

Then there are the guests, they want beer. They order a beer ("WaitSemaphore) and if there is a beer on the table, they are able to take it without waiting time. But if there is no beer left on the table, they need to wait until the barkeeper filled a new glass ("PostSemaphore").



What could you do with it? you could let one task create things which another task processes. The semaphore allows to have multiple task process these things.


@ fork and starving people
Yes, the Mutex restricts usage to a single user. Nobody else is allowed to do something in the mutex-part of your code. it is exclusive for that moment.


bye
Ron


Yue(Posted 2016) [#13]
@Col Thanks


Many thanks col , that very simple explanation has come at a better time , my brain is very simple and is often confused with programming techniques.

@Derron Thanks Yuo too.


Hardcoal(Posted 2016) [#14]
wth is mutex anyway ..


col(Posted 2016) [#15]
Mutex is short for 'Mutual Exclusion'. To be mutually exclusive means there can be only 1. Think of a mutex as a variable that can be put into a locked state. Any thread can put a mutex into a locked state by using LockMutex. You then must unlock the mutex using UnlockMutex from the same thread. When a mutex is in the locked state and another thread calls LockMutex on that mutex then that 'newer' thread is forced to wait until the same thread that locked the mutex unlocks it. When it becomes unlocked then the waiting thread will be allowed to continue executing instructions.