tuto : mutex

Vous débutez et vous avez besoin d'aide ? N'hésitez pas à poser vos questions
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

tuto : mutex

Message par hardy »

J'ai eu, et j'ai vu que d'autres ont eu quelques problèmes avec les threads

C'est juste un petit tuto sur la synchronisation. Il pourra être augmenté par la suite. Ici, je ne vais parler que des mutex (mutal exclusion)

Alors le problème (par exemple) est le suivant : dans un prog, on a une variable globale, disons var, par exemple un tableau.

le programme, dans son exécution crée disons deux threads avec createthread(@proc1(),0) et createthread(@proc2(),0)

avant d'aller plus loin, penser que le prog principal crée lui même un thread : le thread primaire associé au processus.

Donc il y a pour le système 3 threads associés au processus.

Evidemment, windows c'est du "faux multitâche" : il n'y a qu'un processeur... (le "vrai multitâche", c'est quand il y a plusieurs processeurs qui font tourner divers processus en même temps)

Ce qui se passe, c'est que le système gère l'accès au processeur, en donnant régulièrement l'accès aux divers threads en cours, selon divers critères, dont leur niveaux de priorité. (en plus il s'occupe de l'envoi des messages,..., mais ça nous intéresse pas ici)

la variable var est modifiée/lue dans le prog principal et les deux threads.

disons que var est modifiée dans des boucles dans les trois threads.
Alors un thread s'effectue. On est dans la boucle.
Puis en cours de route, le système passe la main à un autre qui modifie aussi var avant que le précédent ai fini sa boucle.
Résultat?
Ben c'est le b..., et les résultats sont aléatoires. Des fois ça marche, des fois non.

Un outil de synchronisation (le plus simple), c'est le mutex

Dans le prog, au début, on crée un mutex:

nommutex.s="salutjesuisunmutex"
hmutex=CreateMutex_(0,0,@nommutex)

On a ainsi créé un mutex avec l'handle hmutex, qui n'est au départ possédé par aucun thread.

On peut alors utiliser deux commandes:

WaitForSingleObject_(hmutex,temps) :
attend que le mutex se libère et en prend possession. temps=temps maximal d'attente en ms. si temps=0, attend indéfiniment.

ReleaseMutex_(hmutex):
relâche le mutex

Alors on encadre chaque séquence d'instructions utilisant var et devant s'effectuer intégralement sans que d'autres modifs de var liées à un autre thread interfèrent entre un WaitForSingleObject_(hmutex,temps) et un ReleaseMutex_(hmutex).

Et y'a plus de problème. (enfin théoriquement
:D )

NB : comment fait-on pour mettre ça en anonce?
Si quelqu'un pouvait le faire.
Et puis cette rubrique pourra être augmentée au fur et à mesure.

Je propose aussi de créer un tuto "communication inter-processus".
Qui commence?
Ombres
Messages : 51
Inscription : sam. 24/janv./2004 12:46
Contact :

Message par Ombres »

Super ca marche bien :)
2 thread se battent pour augmenter ou diminuer var:

Code : Tout sélectionner

Global var
Global quit

Global mutexVar,mutexQuit,mutexDebug
Global threadPlus,threadMoins

Procedure Moins()
  Repeat
    WaitForSingleObject_(mutexVar,0)
      var-1
      WaitForSingleObject_(mutexDebug,0)
        Debug "MOINS! "+Str(var)
      ReleaseMutex_(mutexDebug)
    ReleaseMutex_(mutexVar)
    WaitForSingleObject_(mutexQuit,0)
    If quit = #TRUE
      ReleaseMutex_(mutexQuit)
      WaitForSingleObject_(mutexDebug,0)
        Debug "Arret de Moins"
      ReleaseMutex_(mutexDebug)
      ProcedureReturn
    EndIf
    ReleaseMutex_(mutexQuit)
  ForEver
EndProcedure

Procedure Plus()
  Repeat
    WaitForSingleObject_(mutexVar,0)
      var+1
      WaitForSingleObject_(mutexDebug,0)
        Debug "PLUS! "+Str(var)
      ReleaseMutex_(mutexDebug)
    ReleaseMutex_(mutexVar)
    WaitForSingleObject_(mutexQuit,0)
    If quit = #TRUE
      ReleaseMutex_(mutexQuit)
      WaitForSingleObject_(mutexDebug,0)
        Debug "Arret de Plus"
      ReleaseMutex_(mutexDebug)
      ProcedureReturn
    EndIf
    ReleaseMutex_(mutexQuit)
  ForEver
EndProcedure

mutexVar  = CreateMutex_(0,0,0)
mutexQuit = CreateMutex_(0,0,0)
mutexDebug = CreateMutex_(0,0,0)

If (mutexVar And mutexQuit And mutexDebug) = #FALSE
  Debug "Pas de mutex"
  End
EndIf

threadPlus = CreateThread(@Plus(),0)
threadMoins = CreateThread(@Moins(),0)

If (threadPlus And threadMoins) = #FALSE
  Debug "Pas de thread"
  End
EndIf

OpenWindow(0,0,0,256,0,#PB_Window_SystemMenu,"Fermeture")

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow 

WaitForSingleObject_(mutexQuit,0)
  quit = #TRUE
ReleaseMutex_(mutexQuit)

WaitThread(threadPlus)
WaitThread(threadMoins)

CloseHandle_(mutexVar)
CloseHandle_(mutexQuit)
CloseHandle_(mutexDebug)
J'ai mis un mutex pour que le debuggeur n'ai qu'une chose à afficher à la fois,
mais il y a quand même plusieurs "Debug ..." qui s'affichent sur la même ligne ?!
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

Il faut donner un nom au mutex, et des noms différents pour des mutex différents:

nom.s="..."
h=createmutex_(0,0,nom)
Ombres
Messages : 51
Inscription : sam. 24/janv./2004 12:46
Contact :

Message par Ombres »

Non pas obligé de mettre un nom au mutex:
If lpName is NULL, the mutex object is created without a name.
Dans le doute j'ai quand meme essayé avec des noms, mais ya toujours le probleme du debuggeur... sinon tout fonctionne :)
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

Et concernant les debugs, y'a pas besoin de mutex. C'est une instruction primaire qui ne modifie pas de variable. Peut pas causer de conflit.
Pas oublier : le processeur ne fait qu'une chose à la fois.
Peut pas faire plusieurs debugs en même temps réellement.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

Evidemment, windows c'est du "faux multitâche" : il n'y a qu'un processeur... (le "vrai multitâche", c'est quand il y a plusieurs processeurs qui font tourner divers processus en même temps)
pour la petite histoire windows est bien un system multitache !!


ne pas confondre multitache avec parrallelisme !!
par exemple les processeur "Transputer" etait des composants qui pouvaient etre monte en parrallele, la les "tache" pouvais s'executer en meme temps !!

le multitache se separe en 2 partie
1- le multitache cooperatif
2- le multitache non cooperatif
(on dit prehemptif ou non prehemptif )

le multitache cooperatif c'est: une
tache se lance
une deuxieme tache se lance ;
elle sont executes l'une apres l'autre
tres rapidement ( le processeur leur accorde un peut de temps a chaque fois !! ) un system de priorite est mis en place !!
Le FALCON 030 et L'amiga on des multitache cooperatif !!

le multitache non cooperatif
(windows 3.1) , peut etre bien les autres version ??
chaque tache doit "rendre a main au system"
fonction " DOEVENTS " en visualBasic sert a ça !!
et je dirait Event =WindowEvent() :; ça c'est multitache
Delay(10) en PURE BASIC
car sinon le system reste sur la tache en cours !!!
ce qui explique par exemple que si vous faisiez jouer un son
au demarrage de win 3.1 si votre son durait une heure
il fallait attendre une heure pour pouvoir utiliser la machine !! :)

ça n'etait pas le cas des AMIGA et ATARI FALCON 030 !!

si quelqu'un trouve que j'ai dit une betise n'hesitez pas !!


:lol:
hardy
Messages : 333
Inscription : mer. 02/juin/2004 13:19
Localisation : Tours

Message par hardy »

C'est vrai, en fait je voulais parler de parallèlisme...
C'est pas la même chose.

à Dombro : là je pars prendre mon train... (opéra à Garnier ce soir!)
Verrai ça demain dans l'après-midi.
Répondre