Utilisation des mutex.

Utilisation des mutex

CreateMutex

Voir version :

Pas de dépendances

Télécharger :

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

HANDLE ghMutex;

unsigned long WINAPI fonc1(void* params)
{
    while(1)
    {
        //WaitForSingleObject(ghMutex,INFINITE);
        printf("message du thread ");
        Sleep(1);
        printf("numero 1\n");
        //ReleaseMutex(ghMutex);
    }
    return 0;
}

unsigned long WINAPI fonc2(void* params)
{
    while(1)
    {
        //WaitForSingleObject(ghMutex,INFINITE);
        printf("message du thread ");
        Sleep(1);
        printf("numero 2\n");
        //ReleaseMutex(ghMutex);
    }
    return 0;
}

int main()
{
    HANDLE h1;
    HANDLE h2;
    ghMutex = CreateMutex(NULL,FALSE,NULL);
    h1=CreateThread(NULL,0,fonc1,NULL,0,0);
    h2=CreateThread(NULL,0,fonc2,NULL,0,0);
    getchar();
    CloseHandle(h1);
    CloseHandle(h2);
    CloseHandle(ghMutex);
    return 0;
}



Commentaires

	Reprenons le premier code sur les CreateThread.
	Je crée 2 threads, chacun va juste afficher un message.

	Pour l'instant, ignorez les lignes commentées. Vous pouvez constater que je fais le printf des threads en 2 fois, avec un Sleep(1)
	au milieu (attente de 1 millième de secondes). Je fais ça pour accentuer la probabilité de mettre en évidence ce que je veux.

	Si vous lancez le programme dans l'état, vous vous attendez à une suite de messages bien alignés comme ça :

	message du thread numero 2
	message du thread numero 1
	message du thread numero 2
	message du thread numero 1
	message du thread numero 1
	message du thread numero 2
	message du thread numero 2

	Mais si vous regardez bien, un moment, vous allez tomber sur des trucs comme ça :

	message du thread numero 1
	message du thread numero 1
	numero 2
	message du thread message du
	message du thread numero 2
	message du thread numero 2
	message du thread numero 1

	Que s'est il passé ?
	Et bien il faut savoir que Windows (et pareil pour n'importe quel OS) peut couper un thread n'importe quand pour donner la main à un autre.

	N'importe quand !

	Ici, en l'occurence, il a coupé le thread entre les deux printf (pendant le Sleep). 
	Notez qu'il aurait très bien couper en plein milieu du printf s'il n'y avait eu qu'un seul printf. ça peut vraiment être n'importe quand.

	Cela peut être embêtant. Parfois, on souhaiterait qu'un thread finisse ce qu'il est en train de faire avant que d'autres puissent être appelés.
	En l'occurence ici, on voudrait qu'un thread finisse d'écrire sa ligne, avant que l'autre prenne le relai. Interdire de couper avant la fin
	de la ligne.

	Pour ça, nous définissons ce qu'on appelle un Mutex.
	Un Mutex, pour faire simple, c'est jeton commun à tout le monde.

	Les threads sont des joueurs. Et il n'y a qu'un seul jeton.
	Quand un joueur prend le jeton, il peut travailler. Quand il a fini, il remet le jeton au centre de la table, et un autre peut alors le 
	prendre et travailler.
	Tant qu'un thread n'a pas le jeton, il l'attend. Il guette son retour sur la table pour le prendre à son tour.

	Voila donc l'idée du mutex.

	Décommentez les lignes commentées dans le code, et constatez que plus jamais on a de phrases entremêlées comme vu au dessus.

	Dans le code, j'ai créé un mutex en global. Mais j'aurais très bien pu créer une structure de données, comme vu au chapitre précédent, et donner 
	un pointeur vers le même mutex pour chaque thread.

	Le mutex s'appelle ghMutex. Je le crée avant de lancer les threads.

	http://msdn.microsoft.com/en-us/library/windows/desktop/ms682411(v=vs.85).aspx

	Puis, dans mes threads, je mets la ligne :

	WaitForSingleObject(ghMutex,INFINITE);

	qui veut dire que le thread attend le Mutex (le jeton). INFINITE veut dire qu'il pourra l'attendre indéfiniment s'il le faut.

	Le thread ne passera cette ligne que si le jeton est libre, et il le prend. Après cette ligne, c'est lui et lui seul qui a le jeton.

	Ensuite, il fera ses printf. Et à la fin, on rend le jeton avec ReleaseMutex.
	Il est important de rendre le jeton, sinon, vous coincez tout le monde !

    ************** Danger de Deadlock **************

	La programmation multithread avec mutex peut créer des ennuis si vous n'êtes pas bien rigoureux dans votre gestion des mutex.

	Imaginez que vous ayez 3 threads , A, B et C.

	Si A attend que B ait fini, que B attend que C ait fini, et que C attend que A ait fini, vous êtes en deadlock :
	c'est à dire que plus personne ne bougera, le verouillage de la mort...

	Soyez bien rigoureux la dessus.