web page created Monday 23rd February evening
I have created a simple mut.ual ex.lusion (mutex) example, you can run this from an amigaos shell as it doesnt take input. Dont type control-C or D if run from an AmigaOS shell as it may crash. Control-C etc is fine if you run it from a Geek shell
the main thread creates 30 threads 0 , 1 , ... , 30 and then yields. Different threads correspond to different bracketings: () {} []. Threads 0,1,2 are (), 3,4,5 are {}, 6,7,8 are [], 9,10,11 are () etc,
3 mutexes are created one for each bracketing type, these 3 mutices are arranged in an array.
This is what thread 3 does:
1. it locks the mutex for {}
2. it echoes {
3. it echoes its thread number 3
4. it yields
5. it echoes its thread number 3
6. it echoes }
7. it unlocks the mutex for {}
Thus in total it does:
lock { 3 yield 3 } unlock
now because of the yield other threads will echo their brackets between the { and } but because of the mutual exlusion no further {}s as these are locked out by the mutex.
likewise for all the other threads, so brackets of a given kind will never nest, but can contain brackets of other kinds, thus visually speaking brackets of a given time will be mutually exclusive ie
{ other brackets } other brackets { other brackets },
in theory you could get { [ } ] ie overlap of dissimilar brackets,
Here is some of the output I got:
( 0 { 3 [ 6 0 )( 0 3 }{ 3 6 ][ 6 0 )( 0 3 }{ 3 6 ][ 6 0 ) 3 } 6 ]( 1
For an analogy its like 30 robots red green and blue, where all the red robots share 1 red battery, the green robots share 1 green battery and the blue robots a blue battery.
Thus at any one time there will be at most 3 robots running around each of a different colour!
Well actually if you really slow the film down you will see only 1 robot running around at a time but it will always be 1 of 3 specific differently coloured robots. (there are 3 batteries but only 1 motor, a battery without a motor is not much use!),
The green battery is then a mutex for the green robots, the motor determines the currently active thread,
If you have everything set up correctly you can compile it thus:
gcc mutex.c -o mutex -lpthread020
see the discussion of rhyme.c on how to compile libpthread programs.
The usage of libpthread mutexes is simply:
1. As usual have pthread.h
as the first include:
#include <pthread.h>
2. Declare the mutex structure with constant initialiser values, this could also be dynamically allocated and copied:
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
3. For a given thread to lock the mutex:
pthread_mutex_lock( &my_mutex ) ;
4. The thread relinqueshes the lock thus:
pthread_mutex_unlock( &my_mutex ) ;
SUMMARY:
#include <pthread.h> pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock( &my_mutex ) ; /* join this mutex queue and wait if its busy */ mutually excluded activity, other threads can be active but not ones in this specific mutex queue pthread_mutex_unlock( &my_mutex ) ; /* next thread in mutex queue can now proceed */
AmigaOS provides a global task mutex via Forbid() and Permit(). If the task waits in between then other tasks will reactivate till the waiting is over.
AmigaOS also provides local task mutexes via Semaphores, these are like the above thread mutexes but at the task level. (they are a bit more effort to use as they lie beyond your program)
Thus if AmigaOS tasks are thought of as OS threads then the Semaphores are mutexes,
However because threads are a subdivision of a task the above 2 mechanisms are of no use for thread mutexes. ie if one thread does Forbid() or tries locking a semaphore it wont lock out the other threads of this task.
You could achieve a total locking out of all other tasks and threads via Disable() and Enable() (I think!),
Really thread mutexes have to be done via the specific thread mechanism ie they are a part of the thread scheduling. This is also true of correct threaded sleep statements, if a thread does eg sleep(10) then another thread needs to be activated. If you used an external OS sleep command then all the threads lose the CPU which is a bit clumsy. :although logically it is equivalent. If the sleeps were really tiny it would become inefficient.