Bonjour ,

je dois appliquer le problème des lecteurs/rédacteur (avec priorité au rédacteur) avec les thread en C sous linux. Je n'arrive pas à trouver à quel moment je dois réveiller les threads. Pouvez vous me donner un coup de main ?

Merci d'avance !

Voici mon code :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;
}