Le but de cet exercice est la manipulation des fonctions de création
et d’attente des threads. On pourra faire man pthread(3)
pour
avoir une liste exhaustive des fonctions utilisables pour les
threads. La création de threads se fait avec la fonction
pthread_create(3)
qui prend notamment en argument un
pointeur sur la fonction qu’exécutera le thread.
Écrire un programme qui lance 8 nouveaux threads (en plus de
celui du programme principal) sur une fonction void *start(void *)
qu’on écrira. Cette fonction affichera le PID du processus. Le PID
sera transmis à la fonction start
par pthread_create
par son
dernier argument. N’oubliez pas de compiler avec l’argument
CFLAGS+=-pthread
.
La fonction pthread_join(3)
permet d’attendre un thread
identifié par son THREAD ID (donné lors de l’appel de
pthread_create
. Modifiez le programme précédent pour que le thread
principal attende tous les threads qu’il a créé puis affiche un
message sur la sortie standard.
Ajoutez deux variables entières au programme précédent, l’une
globale, l’autre locale à la fonction start
. Initialiser
les à 0. Incrémentez dans start
les deux variables, affichez
leurs adresses et leurs valeurs. Que se passe-t-il ?
L'équipe Gala de l’Enseirb souhaite améliorer la façon dont elle vend les tickets pour la soirée. Actuellement, une seule personne est responsable de la vente des tickets (tickets.c) et cela nuit à sa bonne présence en cours et les attentes pour obtenir son billet sont bien souvent trop longues.
L'équipe Gala, pour gagner du temps, souhaite
déléguer le travail à un pool de vendeurs de tickets pour paralléliser la vente.
Modifier le programme tickets.c
de façon à ce que le programme
crée 8
étudiants (threads) qui s’occupent en parallèle de la
vente des tickets. Le nombre de tickets à vendre restera une variable
globale.
Chaque étudiant/thread fera la boucle suivante:
sched_yield(3)
pthread_exit(3)
L'équipe Gala (le thread principal) devra récupérer le nombre de billets vendus par chacun des vendeurs et affichera le total de tickets vendus sur la sortie standard.
Expérimentez avec un nombre croissant de billets à vendre. Que se passe-t-il ?
Où est la section critique de ce code ?
Proposez deux modifications de ce programme permettant de mettre la section critique en exclusion mutuelle et de corriger le programme:
Vérifier qu’il n’y a plus le problème observé précédemment dans ces deux versions.
On souhaite améliorer le programme suivant
(lecteurs.c). Ce programme possède deux
fonctions pour un lecteur et un écrivain. Les deux partagent un
tableau A
commun de SIZE éléments.
Un consommateur ne peut lire une case que si le producteur l’a déjà remplie (ou modifée dans ce cas).
Actuellement, le programme proposé possède deux problèmes:
Proposez une modification du programme de telle sorte que deux threads soient créés. Un thread aura le rôle de producteur, le deuxième le rôle du consommateur.
Faites en sorte de garantir l’exécution correcte du programme.
Attention, le lecteur et l'écrivain peuvent lire/écrire intégralement le tableau sans être interrompu par l’autre.
On veut maintenant pouvoir lancer plus d’un thread consommateur. Plusieurs consommateurs peuvent accéder simultanément au tableau A
. Cependant, il faut veiller à ce que chaque consommateur accède à une case différente des autres.
8 philosophes s’assoient autour d’une table ronde pour dîner. Il y a entre chaque convive 1 baguette. Chaque philosophe a besoin de sa baguette de gauche et de celle de droite pour pouvoir commencer à dîner.
Écrire un programme philosophe.c
qui lance 8 threads et qui simule ce
banquet. L’utilisation de chaque baguette sera protégée par un
mutex. La baguette étant disponible si le mutex n’est pas pris, et est
utilisée par un autre philosophe si il est pris.
On supposera également que les philosophes
commencent à prendre leur baguette de droite avant de prendre celle de
gauche. Chaque philosophe aura ainsi le comportement suivant:
void reflechi( int id ) {
printf( "%2d: Je reflechi\n", id );
usleep( random() % 2000 );
printf( "%2d: J'ai faim\n", id );
}
void mange( int id ) {
printf( "%2d: Je mange\n", id );
usleep( random() % 2000 );
printf( "%2d: Je suis repu\n", id );
}
Chaque philosophe effectuera cette operation un nombre de fois assez grand pour révéler d'éventuels problèmes entre threads.