1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
| /*
il y a 4 variables globales , 3 conditions et il faut 1 mutex par variable globale et 1 par condition
Pour les conditions :
- il y a la condition du redacteur qui doit vérifier qu'un autre rédacteur n'utilise pas le fichier
- il y a la condition du redacteur qui doit vérifier qu'un lecteur n'utilise pas le fichier
- il y a la condition du lecteur qui doit vérifier qu'un redacteur n'utilise pas le fichier
*/
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#define nth 20 /* nbre de threads a lancer */
#define ifer(is,mess) if (is==-1) perror(mess)
pthread_t red[nth];
pthread_t lec[nth];
pthread_mutex_t mutex_redaction, mutex_lectures, mutex_lecteur_attente, mutex_redacteur_attente, mutex_cond_red_red, mutex_cond_red_lec,mutex_cond_lec_red;
pthread_cond_t cond_red_red;
pthread_cond_t cond_red_lec;
pthread_cond_t cond_lec_red;
int nb_lectures=0; //4 variables globales
int nb_redaction=0;
int nb_lecteur_attente=0;
int nb_redacteur_attente=0;
/* routine executee dans les threads */
void *pth_lecteur (void *arg)
{
if(nb_redaction==1) //si il y a un redacteur qui est deja sur le fichier le lecteur se met en attente
{
pthread_mutex_lock(&mutex_lecteur_attente);
nb_lecteur_attente++;
pthread_mutex_unlock(&mutex_lecteur_attente);
}
else //sinon il incremente le nb_lectures
{
pthread_mutex_lock(&mutex_lectures);
nb_lectures++;
if(nb_lectures == 1)//si c'est le premier lecteur
{
pthread_mutex_lock(&mutex_redaction);//bloque le mutex redaction pour pas qu'un redacteur puisse ecrire pendant qu'il lit
}
pthread_mutex_unlock(&mutex_lectures);//retire le mutex lectures pour qu'un autre lecteur puisse lire
printf("Lecture\n");//simple affichage de lecture , pas besoin d'acceder au fichier par un fopen
pthread_mutex_lock(&mutex_lectures);//prise de mutex parce qu'il y a utilisation de nb_lectures(ca je suis pas sur ...)
nb_lectures--;
if(nb_lectures==0 && nb_redacteur_attente!=0)//si il n'y a pas de lectures en attente on passe la main au redacteur
{
//envoie signal au redacteur
pthread_cond_wait(&cond_lec_red,&mutex_cond_lec_red);
pthread_mutex_unlock(&mutex_redaction);//on retire le mutex redaction pour laisser l'acces aux redacteurs
pthread_mutex_lock(&mutex_lecteur_attente);//prise du mutex parce qu'il y a operation sur nb_lecteur_attente (pas sur non plus ici)
nb_lecteur_attente--;
pthread_mutex_unlock(&mutex_lecteur_attente);
}
pthread_mutex_unlock(&mutex_lectures);//relachement du mutex lecture
}
return ( (void *)(1));
}
void *pth_redacteur (void *arg)
{
if(nb_redaction==0)//si il n'y a pas de redacteur sur le fichier
{
int is;
is = pthread_mutex_lock(&mutex_redaction);//on prend le mutex pour bloquer la redaction
ifer (is,"err. prise mutex_redacteur");
nb_redaction++;
printf("Ecriture\n");//pas besoin de fopen non plus
is = pthread_mutex_unlock(&mutex_redaction);//on relache le mutex redaction
ifer (is,"err. liberation mutex_redacteur");
nb_redaction--;
if(nb_redacteur_attente!=0)//si il y a des redacteurs en attente
{
//envoie signal au redacteur
pthread_cond_wait(&cond_red_red,&mutex_cond_red_red);
pthread_mutex_lock(&mutex_redacteur_attente);//prise du mutex car utilisation de nb_redacteur_attente(pas sur)
nb_redacteur_attente--;
pthread_mutex_unlock(&mutex_redacteur_attente);
}
else if(nb_redacteur_attente==0 && nb_lecteur_attente==0)//si il n'y a ni redacteur ni lecteur dans la liste
{
//ne rien faire
}
else
{
//envoyer signal aux lecteurs
pthread_cond_wait(&cond_red_lec,&mutex_cond_red_lec);
}
}
else // si il y a un redacteur sur le fichier
{
pthread_mutex_lock(&mutex_redacteur_attente);//prise de mutex pour utilisation de nb_redacteur_attente
nb_redacteur_attente++;//on rajoute un redacteur sur la liste d attente
pthread_mutex_unlock(&mutex_redacteur_attente);
}
return ( (void *)(1) );
}
int main(void)
{
int is, i;
void *val =0;
pthread_mutex_init(&mutex_redaction, NULL);
pthread_mutex_init(&mutex_lectures, NULL);
pthread_mutex_init(&mutex_lecteur_attente, NULL);
pthread_mutex_init(&mutex_redacteur_attente, NULL);
pthread_mutex_init(&mutex_cond_red_red, NULL);
pthread_mutex_init(&mutex_cond_red_lec, NULL);
pthread_mutex_init(&mutex_cond_lec_red, NULL);
/* créer les threads */
for(i=0;i<nth;i++)
{
printf("creation thread lecteur \n");
is = pthread_create( &lec[i], NULL, pth_lecteur, (void *)i );
ifer (is,"err. creation thread lecteur");
}
for(i=0;i<nth;i++)
{
printf("creation thread redacteur \n");
is = pthread_create( &red[i], NULL, pth_redacteur, (void *)i );
ifer (is,"err. creation thread redacteur");
}
/* attendre fin des threads */
for(i=0; i<nth; i++)
{
is = pthread_join( lec[i], &val);
ifer (is,"err. join thread");
printf("ici main, fin lec %d\n",(int)val);
}
for(i=0; i<nth; i++)
{
is = pthread_join( red[i], &val);
ifer (is,"err. join thread");
printf("ici main, fin red %d\n",(int)val);
}
return 0;
} |
Partager