IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Concurrence et multi-thread Java Discussion :

[Thread] synchronisation globale


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    88
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 88
    Points : 72
    Points
    72
    Par défaut [Thread] synchronisation globale
    Bonjour à tous !

    Pardon pour ce titre on ne peut plus généraliste mais je n'aurais pas pu faire plus clair sans rentrer dans les détails.

    Mon problème est le suivant : je souhaite réaliser une application distribuée qui se charge de décomposer un "Job" en un certain nombre de plus petits "Jobs" (ex : le calcul de Pi à un certain nombre de décimale près)
    Chaque petit job sera exécuté dans un thread à part. (Dans notre exemple, le premier thread calcule les 10 premières décimales, le second les 10 suivantes, et ainsi de suite...)

    Au final, le Thread principal se charge donc de lancer autant de threads qu'il faut, les initialise correctement (Dans notre exemple, il indique les bornes de calcul, soit [0-10] pour le 1er thread, [11-20] pour le 2e...), et attend que chaque thread ait fini.

    Je voudrais notifier l'utilisateur à chaque fin de petit job, pour qu'il voit qu'une étape est franchie.
    Pour cela je pensais faire une boucle avec un wait() mais je pense que ca ne correspond pas exactement à ce que je recherche.

    En effet si on boucle de 0 à nb_thread en faisant un wait() sur le thread i [hum, suis-je assez clair ?], il se peut que le thread i+1 ait déja terminé et que le thread i attende encore. Lorsque le thread i aura finalement calculé sa partie, nous aurons donc la notification de fin de l'étape i et en même temps celle de l'étape i+1.

    Ce que j'aimerais avoir comme fonction (si le JDK veut bien me la proposer), ce serait une autre fonction qui met le Thread principal en veille et qui le réveille dès qu'un thread quelconque a fini son exécution. En somme, pour les adeptes du C, ce serait l'équivalent d'un select qu'il me faudrait.
    Il me semble que ce soit possible avec un (une ?) sémaphore et un notify() dès qu'un thread a fini son exécution, mais j'aimerai éviter autant que possible de déployer ce mécanisme.

    Bon, j'ai fait quelques recherches (quand même...) dans la fac, sur la doc de l'API, sur les tutos, mais je n'ai pas trouvé une fonction qui me convenait. Mais je pense qu'un mécanisme comme celui que je viens de décrire n'est pas hors du commun, donc la solution a du certainement glisser au travers des mailles du filet de mes recherches.
    Je fais donc appel au puit de savoir qu'est ce site pour m'indiquer une manière de faire ou au moins un lien qui me l'expliquerait.

    Par avance, merci.
    Joe.

    P.S.: Sorry pour le pavé...

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 95
    Points : 140
    Points
    140
    Par défaut
    Bon, je suis pas sûr d'avoir tout compris, alors je commence par résumer le problème. Tu cherches en fait à avoir un Thread principal (une sorte de chef) qui va piloter un certain nombres de Threads, et à qui il va déléguer le travail. Et et quand un Thread "exécutif" a fini son travail, il en informe son "chef", sachant qu'il n'y a pas d'hypothèse sur l'ordre.

    Alors voilà comment je vois ça en Java. Ton Thread "chef" crée et lance ses Threads "exécutifs", puis il s'endors avec wait(). Et à chaque fois qu'un Thread exécutif termine son travail, il réveille le Thread "chef" avec notify() (désolé pour la métaphore, les chefs vont pas être content !! lol !!!!). Et à chaque fois que le chef est réveillé, il regarde l'état de chacun des exécutifs (car plusieurs d'entre eux peuvent finir en même temps).

    Bref, pour résumer, on peut utiliser les méthodes wait() et notify() sur le Thread principal, sans avoir recours aux sémaphores.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    88
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 88
    Points : 72
    Points
    72
    Par défaut
    Ah ok, j'avais donc bel et bien mal interprété la documentation...
    Il faut faire et non Effectivement, ca parait assez clair comme ça. Je devais ne pas avoir les yeux en face des trous...
    Et donc ainsi ce sera le premier thread qui arrivera a terme (fera le notify(), donc) qui réveillera le thread principal (ou chef...) Ce ne sera pas suivant une liste. Je pense que le code équivalent donne à peu près ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    for(i=0;i<nb_threads;i++)
        threads[i].start();
     
    for(i=nb_threads; i>0;)
    {
        this.wait();
        i = this.activeCount();
        System.out.println("Il reste "+i+" thread(s) en cours");
    }
    pour ce qui est du thread "chef" et pour les autres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void run()
    {
        while(isRunning)
        {
            // traitement
        }
        this.notify();
    }
    Est ce que j'ai de nouveau mal interprêté le mécanisme, ou je me rapproche (enfin) du vrai ? Ca a sa logique mais je n'arrive pas à m'y faire...
    Merci en tout cas pour l'éclairage

    @bientôt
    Joe

    P.S.: pffiou quelle activité sur ce forum... :o

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 95
    Points : 140
    Points
    140
    Par défaut
    Est ce que j'ai de nouveau mal interprêté le mécanisme, ou je me rapproche (enfin) du vrai ?
    C'est pas tout à fait ça. Les wait() / notify() doivent être fait sur le thread principal. Donc les Threads "exécutifs" doivent avoir une référence du Thread père, un truc comme ça :

    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
    public class Executif extends Thread {
      private Thread threadPrincipal;
      private boolean isWorking;
     
      public Executif(Thread threadPrincipal) {
        this.threadPrincipal = threadPrincipal;
      }
     
      public synchronized void setWorking(boolean isWorking) {
        this.isWorking = isWorking;
      }
     
      public synchronized boolean isWorking() {
        return isWorking;
      }
     
      public void run() {
        setWorking(true);
        // faire son traitement
        fin();
      }
     
      public synchronized void fin() {
        setWorking(false);
        threadPrincipal.notify();
      }
     
    }
    Ensuite, pour le Thread principal, il ne faut pas faire de for, mais plutôt un "tant qu'il reste des Thread qui n'ont pas fini" (sinon, il risque d'y avoir des problèmes quand des threads terminent en même temps). Et pour cela, le Thread parent doit appeller le isWorking() sur chacun des Threads. Donc ça doit être un truc comme ça :

    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
    for(i=0;i<nb_threads;i++) {
      threads[i] = new Executif(Thread.currentThread());
      threads[i].start();
    }
    nbWorkingThread = getNbWorkingThread();
    while(nbWorkingThread > 0) {
      System.out.println("Il reste "+nbWorkingThread +" thread(s) en cours");
      wait();
      nbWorkingThread = getNbWorkingThread();
    }
     
    public int getNbWorkingThread() {
      int count = 0;
      for(i=0 ; i<threads.length ; i++) {
        if (threads[i].isWorking()) count++;
      }
      return count;
    }
    Bon, j'ai pas du tout testé, faut voir ça plutôt comme une base de départ.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    88
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 88
    Points : 72
    Points
    72
    Par défaut
    Ok je pense avoir compris globalement maintenant. Merci beaucoup.
    Encore quelques petits détails...
    Chaque instance de Executif aura sa propre valeur de isWorking. Mais, si on l'avait mis synchronized n'y aurait-il eu qu'une seule variable isWorking répartie entre les threads ? Est-ce que la portée de la variable (euh je sais pas si on utilise le terme portée pour désigner 'private', 'public', 'protected'...) y change quelque chose ?

    Sinon,pour le thread principal, activeCount() ne marche pas ?
    Comme la fonction est appelée après le wait(), le notify() aura été exécuté, et le thread Executif sorti de son run(). Donc ce dernier ne devrait pas être comptabilisé par activeCount(), ou bien ?...

    Merci pour ces réponses en tout cas, elles m'ont déjà bien aidé à comprendre le mécanisme. Je sors de TPs en MPI et UPC alors les threads en Java, ça me parle pas trop...

    @bientôt
    Joe.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    95
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 95
    Points : 140
    Points
    140
    Par défaut
    Mais, si on l'avait mis synchronized n'y aurait-il eu qu'une seule variable isWorking répartie entre les threads ?
    Je ne pense pas. C'est le mot clé static pour désigner qu'une variable est commune entre les instances d'une même classe. Le synchronized sert à gérer les accès concurrentiels.

    Sinon,pour le thread principal, activeCount() ne marche pas ?
    Si, ça peut marcher, à condition de ne pas avoir d'autres Threads dans le programme. Sinon, je crois qu'il existe des ThreadGroup pour justement regrouper des Threads entre eux. Je sais pas trop comment ça marche, mais ça peut être intéressant de regarder de ce côté là.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    88
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 88
    Points : 72
    Points
    72
    Par défaut
    Ok je garde donc ton code sous la main au cas où le mien ne marche pas (hey, faut quand même qu'il reste quelque chose de mon code, non ? )
    De toute facons, je n'ai pas d'autres threads dans mon programme, donc il n'y a pas de raisons que ca marche pas...

    Merci encore pour cette aide.

    @bientôt,
    Joe.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Thread] Synchronisation
    Par Flitz dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 04/04/2006, 08h38
  2. Thread Synchronisation avec structure FIFO ??
    Par vincedom dans le forum MFC
    Réponses: 5
    Dernier message: 30/03/2006, 06h00
  3. [Threads] Synchronisation
    Par InDaWinD dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 20/02/2006, 15h11
  4. Réponses: 1
    Dernier message: 23/05/2005, 15h52
  5. [Thread][Synchronisation] Exclusion mutuelle
    Par masto dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 20/01/2005, 16h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo