【问题标题】:Thread rendez vous monitor线程会合监控器
【发布时间】:2017-11-10 14:06:42
【问题描述】:

我正在尝试使用监视器和互斥锁实现一个集合点,但它并没有真正起作用。我希望你能帮助我看到这个问题。代码如下:

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

【问题讨论】:

  • 如果你的日志是英文的,阅读你的代码会容易得多。
  • 开始 = 开始 / 结束 = 结束
  • 您显示的代码不完整。
  • 请用英文。

标签: c posix mutex


【解决方案1】:

您的代码中最重要的问题似乎是当iRdv 计数器达到NB_RDVtraitement_principal() 调用pthread_cond_signal()。这将唤醒 一个 线程等待条件变量,但您需要唤醒多个线程。为此,您应该致电 pthread_cond_broadcast()

但是,如果您想可靠地准确唤醒 NB_RDV 线程并允许它们继续,那么您还有一个问题。在向 CV 广播的线程释放互斥锁后,您不能确信刚刚唤醒的线程会在等待它的任何其他线程获取它之前全部重新获取它。如果在traitement() 中等待的线程首先获取它,那么该线程将进入traitement_principal() 并在唤醒线程继续之前将continuer 重置为0,导致后者在最终自己重新获取互斥锁时继续等待.

如果 任何 NB_RDV 线程可以在达到该数量后继续通过障碍 - 可能包括在 NB_RDVth之后到达它的线程>,那么你可以通过一些修改来实现。与其将continuer 实现为标志,不如将其设置为计数器,其值在任何给定时间指示有多少线程可以继续通过集合点而无需(进一步)等待。

另一方面,如果您需要确保第一个到达集合点的NB_RDVth 线程也最先离开,那么我认为您需要添加一些跟踪其到达顺序的共享状态形式。

【讨论】:

  • 谢谢,确实,我使用广播后看到了这个问题。我将尝试按照您所说的方式使用计数器来执行此操作,但实际上令人讨厌的是,我认为有一个带有条件的函数来查看条件是否为空的等待线程。但我找不到这方面的任何信息。
  • 不,@Minirock,Pthreads 没有测试等待条件变量的线程数的功能。但是您可以将这样的计数器与条件变量一起包装在您自己的数据结构中,这确实大致是您所做的。这在这里为您的特定目的服务,但它通常没有您想象的那么有用。
  • 看起来和我在课堂上看到的完全不同。理论上监视器之类的东西应该能够自己实现互斥......但实际上在C语言中我们必须使用互斥锁来实现......总是在理论上,老师告诉我们有一个像cond这样的condtion函数.empty 告诉我们进程是否正在等待监视条件。下次我应该记住这一点。
  • 嗯,是的,@Minirock,理论和实践之间经常存在差异,而且您研究的理论结构(例如监视器)可能与您可用的实际工具不完全对应。特别是,Pthreads 库根本不提供监视器。相反,它直接提供了监视器的独立组件——互斥锁和条件变量。您可以根据这些构建自己的监视器或独立使用它们(至少是互斥体)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多