线程预约监视器
Thread rendez vous monitor
我正在尝试使用监视器和互斥锁实现一个集合点,但它并没有真正起作用。我希望你能帮助我看到这个问题。这是代码:
void traitement_principal(){
if(iRdv==NB_RDV){
iRdv=0;
continuer=1;
pthread_cond_signal(&autoContinuer);
}else{
continuer=0;
}
while(continuer!=1){
pthread_cond_wait(&autoContinuer,&emAffichage);
}
printf("Thread %lu, je finis mon traitement mon traitement \n",pthread_self());
}
void* traitement(){
pthread_mutex_lock (&emAffichage);//demande accès
printf("Thread %lu, je commence mon traitement \n",pthread_self());
iRdv+=1;
traitement_principal();
pthread_mutex_unlock (&emAffichage);//rend accès
pthread_exit((void *)NULL);
}
void thdErreur(int codeErr, char *msgErr, void *codeArret) {
fprintf(stderr, "%s: %d soit %s \n", msgErr, codeErr, strerror(codeErr));
pthread_exit(codeArret);
}
int main(int argc, char const *argv[]){
int etat;
pthread_t idThd[NB_THREADS];
for(int i = 0; i < NB_THREADS; i++){
if ((etat = pthread_create(&idThd[i], NULL, traitement,NULL)) != 0)
thdErreur(etat, "Creation thread avec rdv",NULL);
}
for (int i = 0; i < NB_THREADS; i++)
if ((etat = pthread_join(idThd[i], NULL)) != 0)
thdErreur(etat, "Join threads afficheurs", NULL);
printf ("\nFin de l'execution du thread principal \n");
return 0;
}
NB_RDV
是一个扩展为 3
.
的宏
iRDV
是初始化为 0
.
的文件范围变量
continuer
是初始化为 0
.
的文件范围变量
这里是程序输出的例子:
这不是我想要的。例如,对于第一个,我想得到
Thread 0 I start
Thread 1 I start
Thread 2 I start
Thread 0 I end
Thread 1 I end
Thread 2 I end
您的代码中最严重的问题似乎是 traitement_principal()
在 iRdv
计数器达到 NB_RDV
时调用 pthread_cond_signal()
。这将唤醒一个个等待条件变量的线程,但是你需要唤醒多个线程。为此,您应该改为调用 pthread_cond_broadcast()
。
但是如果你想准确地唤醒 NB_RDV
线程并允许它们继续,那么你还有一个问题。在广播到 CV 的线程释放互斥锁后,您不能确信刚刚唤醒的线程会在等待它的任何其他线程获取它之前全部重新获取它。如果在 traitement()
中等待的线程首先获取它,则该线程将进入 traitement_principal()
并在唤醒线程继续之前将 continuer
重置为 0
,从而导致后者恢复它们等待他们最终自己重新获得互斥量。
如果 any NB_RDV
线程在该数字达到它之后继续越过障碍 - 可能包括在 [=13 之后到达它的线程=]th,那么你可以通过一些修改来实现。不要将 continuer
实现为一个标志,而是将其设置为一个计数器,其值在任何给定时间指示有多少线程可以继续通过集合点而无需(进一步)等待。
另一方面,如果你需要保证第NB_RDV
th个线程到达集合点也是第一个离开,那么我认为您需要添加某种形式的共享状态来跟踪它们的到达顺序。
我正在尝试使用监视器和互斥锁实现一个集合点,但它并没有真正起作用。我希望你能帮助我看到这个问题。这是代码:
void traitement_principal(){
if(iRdv==NB_RDV){
iRdv=0;
continuer=1;
pthread_cond_signal(&autoContinuer);
}else{
continuer=0;
}
while(continuer!=1){
pthread_cond_wait(&autoContinuer,&emAffichage);
}
printf("Thread %lu, je finis mon traitement mon traitement \n",pthread_self());
}
void* traitement(){
pthread_mutex_lock (&emAffichage);//demande accès
printf("Thread %lu, je commence mon traitement \n",pthread_self());
iRdv+=1;
traitement_principal();
pthread_mutex_unlock (&emAffichage);//rend accès
pthread_exit((void *)NULL);
}
void thdErreur(int codeErr, char *msgErr, void *codeArret) {
fprintf(stderr, "%s: %d soit %s \n", msgErr, codeErr, strerror(codeErr));
pthread_exit(codeArret);
}
int main(int argc, char const *argv[]){
int etat;
pthread_t idThd[NB_THREADS];
for(int i = 0; i < NB_THREADS; i++){
if ((etat = pthread_create(&idThd[i], NULL, traitement,NULL)) != 0)
thdErreur(etat, "Creation thread avec rdv",NULL);
}
for (int i = 0; i < NB_THREADS; i++)
if ((etat = pthread_join(idThd[i], NULL)) != 0)
thdErreur(etat, "Join threads afficheurs", NULL);
printf ("\nFin de l'execution du thread principal \n");
return 0;
}
NB_RDV
是一个扩展为 3
.
iRDV
是初始化为 0
.
continuer
是初始化为 0
.
这里是程序输出的例子:
这不是我想要的。例如,对于第一个,我想得到
Thread 0 I start
Thread 1 I start
Thread 2 I start
Thread 0 I end
Thread 1 I end
Thread 2 I end
您的代码中最严重的问题似乎是 traitement_principal()
在 iRdv
计数器达到 NB_RDV
时调用 pthread_cond_signal()
。这将唤醒一个个等待条件变量的线程,但是你需要唤醒多个线程。为此,您应该改为调用 pthread_cond_broadcast()
。
但是如果你想准确地唤醒 NB_RDV
线程并允许它们继续,那么你还有一个问题。在广播到 CV 的线程释放互斥锁后,您不能确信刚刚唤醒的线程会在等待它的任何其他线程获取它之前全部重新获取它。如果在 traitement()
中等待的线程首先获取它,则该线程将进入 traitement_principal()
并在唤醒线程继续之前将 continuer
重置为 0
,从而导致后者恢复它们等待他们最终自己重新获得互斥量。
如果 any NB_RDV
线程在该数字达到它之后继续越过障碍 - 可能包括在 [=13 之后到达它的线程=]th,那么你可以通过一些修改来实现。不要将 continuer
实现为一个标志,而是将其设置为一个计数器,其值在任何给定时间指示有多少线程可以继续通过集合点而无需(进一步)等待。
另一方面,如果你需要保证第NB_RDV
th个线程到达集合点也是第一个离开,那么我认为您需要添加某种形式的共享状态来跟踪它们的到达顺序。