交替线程打印C

时间:2017-09-22 09:22:47

标签: c mutex

我希望用线程打印一些(nbFois)。我做到了,但以下代码存在问题。只有当所有线程都获得相同的nbFois次时,这才有效。

这里使用的是nbAffichage [i] = 5个foreach线程。 但是如果nbAffichage是随机的(例如,第一个是3 ......第二个是6);然后当第一个结束时第二个无法启动。

/* Lancer les threads afficheurs */
  for (i = 0; i < nbThreads; i++) {
    //nbAffichages[i] = rand() % NB_AFFICHAGES;
    nbAffichages[i] = 5;
    if ((etat = pthread_create(&idThdAfficheurs[i], NULL,
                               thd_afficher, &nbAffichages[i])) != 0)
      thdErreur(etat, "Creation afficheurs", NULL);
  }

打印功能

void *thd_afficher (void *arg) {
  int i, j, nbLignes;
  int *nbFois = (int *)arg;
  int monMut=tMut.indiceT[iAffiche];
  iAffiche=(iAffiche+1)%nbThreads;
  for (i = 0; i < *nbFois; i++) {
    nbLignes = rand()% (*nbFois);
    //nbLignes = 3;
    //l'affichage est trop rapide pour voir la différence
    pthread_mutex_lock (&tMut.m[monMut]);//demande accès
    for (j = 0; j < nbLignes; j++) {
      printf("Thread %lu, j'affiche %d-%d--------%d lignes\n", pthread_self(), i, j,nbLignes);
      usleep(10);
    } 
    pthread_mutex_unlock (&tMut.m[(monMut+1)%nbThreads]);//rend accès 
  }
  /* Se terminer sans renvoyer de compte-rendu */
  pthread_exit((void *)NULL);
}

全局线程结构

typedef struct ThreadId ThreadId;
struct ThreadId
{
    int indiceT[NB_THREADS_MAX];
    pthread_mutex_t m[NB_THREADS_MAX];
};

ThreadId tMut;

感谢您的帮助。

编辑:整个代码

/* nbThread affichent un message a l'ecran
   Parametre du programme : nbThread
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define NB_THREADS_MAX  20
//#define NB_FOIS         2


typedef struct ThreadId ThreadId;
struct ThreadId
{
    int indiceT[NB_THREADS_MAX];
    pthread_mutex_t m[NB_THREADS_MAX];
};

ThreadId tMut;//variable de structure avec le tableau de threads et d'indice correespondant
//Mutex ayant le droit d'écrire au début
int iAffiche=0;
int nbThreads=-1;
/*---------------------------------------------------------------------*/
/* Afficher un message d'erreur en fonction du code erreur obtenu
*/
void thdErreur(int codeErr, char *msgErr, void *codeArret) {
  fprintf(stderr, "%s: %d soit %s \n", msgErr, codeErr, strerror(codeErr));
  pthread_exit(codeArret);
}

/*---------------------------------------------------------------------*/
/* Fonction executee par un thread : afficher un message un certain nombre
  de fois nbFois a l'ecran, nbLignes lignes de messages ou nbLignes et
  genere aleatoirement
  Parametre de creation du thread : nbFois, le nombre d'affichages
*/
void *thd_afficher (void *arg) {
  int i, j, nbLignes;
  int *nbFois = (int *)arg;
  int monMut=tMut.indiceT[iAffiche];
  iAffiche=(iAffiche+1)%nbThreads;
  for (i = 0; i < *nbFois; i++) {
    //nbLignes = rand()% (*nbFois);
    nbLignes = 3;
    //l'affichage est trop rapide pour voir la différence
    pthread_mutex_lock (&tMut.m[monMut]);//demande accès
    for (j = 0; j < nbLignes; j++) {
      printf("Thread %lu, j'affiche %d-%d--------%d lignes\n", pthread_self(), i, j,nbLignes);
      usleep(10);
    } 
    pthread_mutex_unlock (&tMut.m[(monMut+1)%nbThreads]);//rend accès 
  }
  /* Se terminer sans renvoyer de compte-rendu */
  pthread_exit((void *)NULL);
}

/*---------------------------------------------------------------------*/
#define NB_AFFICHAGES 10

int main(int argc, char*argv[]) {
  pthread_t idThdAfficheurs[NB_THREADS_MAX];
  int i, etat;

  int nbAffichages[NB_THREADS_MAX];
  if (argc != 2) {
    printf("Usage : %s <Nb de threads>\n", argv[0]);
    exit(1);
  }

  nbThreads = atoi(argv[1]);
  if (nbThreads > NB_THREADS_MAX)
    nbThreads = NB_THREADS_MAX;

  //initialisation des mutex
  for (int k = 0; k < nbThreads; k++){
    tMut.indiceT[k]=k;
    pthread_mutex_init(&tMut.m[k],NULL);//tout les mutex init à 1
    if(k!=0){
      pthread_mutex_lock (&tMut.m[k]);//On retire l'accès à tous les mutex sauf le premier
    }
  }


  /* Lancer les threads afficheurs */
  for (i = 0; i < nbThreads; i++) {
    //nbAffichages[i] = rand() % NB_AFFICHAGES;
    nbAffichages[i] = 5;
    if ((etat = pthread_create(&idThdAfficheurs[i], NULL,
                               thd_afficher, &nbAffichages[i])) != 0)
      thdErreur(etat, "Creation afficheurs", NULL);
  }

  /* Attendre la fin des threads afficheur car si le thread principal
    - i.e. le main() - se termine, les threads fils crees meurent aussi */
  for (i = 0; i < nbThreads; i++)
    if ((etat = pthread_join(idThdAfficheurs[i], NULL)) != 0)
      thdErreur(etat, "Join threads afficheurs", NULL);

  printf ("\nFin de l'execution du thread principal \n");
  return 0;
}

1 个答案:

答案 0 :(得分:1)

iAffiche的作业有竞争条件。即使假设顺利,你的线程然后锁定“他们自己的”互斥锁(monMut),然后解锁他们的邻居!看起来你想要向下传递一个令牌(当线程想要循环不同次数时很可能失败),但你根本就不能使用这样的互斥量。

您可以尝试使用semaphores数组。将它们初始化为0,除了第一个线程,它使得1.然后,在所有线程中循环相同的次,每个线程等待其信号量,它的工作是否正常(或者如果它的{ {1}}值太小),然后提升下一个线程的信号量。您最终再次处于初始状态,信号量向量为(1,0,0,...)。