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

API standards et tierces Java Discussion :

[RMI] RMI et synchronisation


Sujet :

API standards et tierces Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé Avatar de Satch
    Homme Profil pro
    Hypnothérapeute - Magicien
    Inscrit en
    Mars 2004
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Suisse

    Informations professionnelles :
    Activité : Hypnothérapeute - Magicien

    Informations forums :
    Inscription : Mars 2004
    Messages : 498
    Par défaut [RMI] RMI et synchronisation
    Bonjour,

    J'ai un serveur RMI qui expose un objet contenant un message, que les clients peuvent modifier et récupérer.

    Je lance 100 threads clients qui font ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            for(int i=0;i<100;i++){
            	HelloInterface hello = (HelloInterface) Naming.lookup("//127.0.0.1/Hello");
            	synchronized (hello) {
                	hello.setMessage(getName());
                	System.out.println (getName()+" : "+hello.getMessage());
    	        }
     
          }
    Et là je m'apperçois que le bloc synchronizé ne marche pas. En effet j'ai des sorties de ce genre :

    Thread-45 : Thread-52
    Thread-18 : Thread-52
    Thread-52 : Thread-52
    Thread-45 : Thread-45
    Ce qui signifie que la synchronisation ne se passe pas comme prévu.

    Ma question est simple : comment gérer la synchronisation avec RMI ??

  2. #2
    Membre émérite
    Avatar de divxdede
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    525
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Avril 2004
    Messages : 525
    Par défaut
    Citation Envoyé par Satch Voir le message
    Bonjour,

    J'ai un serveur RMI qui expose un objet contenant un message, que les clients peuvent modifier et récupérer.

    Je lance 100 threads clients qui font ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            for(int i=0;i<100;i++){
            	HelloInterface hello = (HelloInterface) Naming.lookup("//127.0.0.1/Hello");
            	synchronized (hello) {
                	hello.setMessage(getName());
                	System.out.println (getName()+" : "+hello.getMessage());
    	        }
     
          }
    Et là je m'apperçois que le bloc synchronizé ne marche pas. En effet j'ai des sorties de ce genre :



    Ce qui signifie que la synchronisation ne se passe pas comme prévu.

    Ma question est simple : comment gérer la synchronisation avec RMI ??
    L'operation de synchronisation de java n'est pas distribué.
    lorsque tu écrits synchronized(hello) ton thread courant obtient/attend le moniteur sur l'instance "hello" mais c'est une instance de ta jvm locale, elle n'a pas de lien directe avec des objets de la jvm distante (même si il s'agit d'un stub)
    Dans ton cas tu ne fait que synchroniser un des clients vis a vis de ces propres threads mais pas les n-clients entre eux.

    De plus probablement que la méthode Naming.lookup(...) puisse retourner plusieurs instances de stub (a faire confirmer), si c'est le cas tu ne peu pas synchroniser tes threads sur cette instance.

  3. #3
    Membre éprouvé Avatar de Satch
    Homme Profil pro
    Hypnothérapeute - Magicien
    Inscrit en
    Mars 2004
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Suisse

    Informations professionnelles :
    Activité : Hypnothérapeute - Magicien

    Informations forums :
    Inscription : Mars 2004
    Messages : 498
    Par défaut
    La question reste donc ouverte.
    Comment faire pour qu'un seul client à la fois puisse accéder à l'objet distant ?

    un setLock et releaseLock sur l'objet qui mettrait un boolean à true ou false ? Plusieurs threads pourraient passer dans le setLock en même temps donc non.
    Je ne vois vraiment pas de solution. Et j'ai beau chercher, je ne trouve pas de ressource parlant de ce sujet.

  4. #4
    Membre habitué
    Inscrit en
    Juin 2007
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 14
    Par défaut
    Hummm... Je n'ai pas bien saisi une chose... tu as juste plusieurs threads ou tu as également plusieurs clients (plusieurs processus ayant chaqun plusieurs threads) ?

    Si tu as simplement plusieurs threads ton code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    for(int i=0;i<100;i++){
            	HelloInterface hello = (HelloInterface) Naming.lookup("//127.0.0.1/Hello");
            	synchronized (hello) {
                	hello.setMessage(getName());
                	System.out.println (getName()+" : "+hello.getMessage());
    	        }
     
          }
    Ne fonctionnne pas (n'est pas synchronisé) tout simplement car chaque thread possede son propre objet "hello" et donc le verrou ne sers a rien...

    Tu dois donc utiliser un objet que tous les threads vont partager (soit une variable static de tes thread soit une variable commune que tu leur passe en parametre)

    exemple avec la variable statique :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class MonThread extends Thread {
       private static final Object monVerrou = new Object() ;
     
       public void run {
          for(int i=0;i<100;i++){
             HelloInterface hello = (HelloInterface) Naming.lookup("//127.0.0.1/Hello");
             synchronized (monVerrou) {
                hello.setMessage(getName());
                System.out.println (getName()+" : "+hello.getMessage());
             }
          }
       }
    }
    exemple avec la variable en parametre :

    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
     
    class MonThread extends Thread {
       private Object monVerrou ;
     
       public MonThread(Object monVerrou) {
          this.monVerrou = monVerrou ;
       }
     
       public void run {
          for(int i=0;i<100;i++){
             HelloInterface hello = (HelloInterface) Naming.lookup("//127.0.0.1/Hello");
             synchronized (monVerrou) {
                hello.setMessage(getName());
                System.out.println (getName()+" : "+hello.getMessage());
             }
          }
       }
    }
    Voila ... Apres si tu as plusieurs clients la effectivement ca devient plus compliqué !

  5. #5
    Membre expérimenté Avatar de Amine_sas
    Profil pro
    Étudiant
    Inscrit en
    Juin 2005
    Messages
    245
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2005
    Messages : 245
    Par défaut
    Salut,
    Il s'agit, je pense, d'un probleme de synchronisation dans un milieu distribué qui est differente de celle sur un seul poste.
    Les recherches qui ont été menées tracent 4 types d'algorithmes comme solution:
    1- Centralisée: les differents process ou threads distribués doivent se mettre d'accord sur sun poste et le choisissent comme coordinateur. Toute ressource doit etre demandée aupres du coordinateur; il en va de meme pour la liberation.
    l'inconvenient de cette approche est que en cas où le coordinateur tombe en panne tout le systeme s'arrete.

    2- Decentralisée: n coordinateurs au lieu de 1, un process doit obtenir au moins (n/2 + 1) voix pour acceder a la ressource. Inconvenients: famine, efficacité modeste.

    3- Distribuée: tout process doit avoir l'accord de tous les autre process. Probleme: panne d'un process.

    4- Token ring: un process doit attendre que le jeton arrive pour entrer en section critique. s'il n'exite aucun process voulant acceder a la ressource, le jeton circule indéfiniment. Problemes: perte du jeton, panne d'un processus.

    Pour plus d'informations voir Distributed Systems par Andrew Tanenbaum et Maarten Van Steen.

  6. #6
    Membre éprouvé Avatar de Satch
    Homme Profil pro
    Hypnothérapeute - Magicien
    Inscrit en
    Mars 2004
    Messages
    498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Suisse

    Informations professionnelles :
    Activité : Hypnothérapeute - Magicien

    Informations forums :
    Inscription : Mars 2004
    Messages : 498
    Par défaut
    Il s'agit bien d'avoir plusieurs clients.

    Typiquement le serveur exposerait un objet que plusieurs clients peuvent modifier et lire.

    Je pensais qu'il existait un moyen "simple" de faire la synchronisation avec RMI. Apparemment pas.

    Je vais fouiller un peu ces 4 méthode. Je pense que la première a l'air la plus simple à mettre en oeuvre.

    Si vous aviez un ou des exemples de mise en oeuvre d'une des méthodes avec RMI, je suis preneur. Sinon ben je vais suer un peu

  7. #7
    Membre expérimenté
    Inscrit en
    Mai 2007
    Messages
    335
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 335
    Par défaut
    Bonjour,
    c'est un sujet intéressant.
    cas du jeton
    Pour commencer, si tu veux placer un jeton, tu peux synchroniser une méthode côté serveur: un seul client disposera du jeton.
    Mais c'est effectivement assez risqué, il suffit qu'un client plante pour bloquer tout le monde, et de plus même en fonctionement normal, ça ralenti tout le monde.
    On peut néanmoins s'affranchir d'une partie du problème en ajoutant en plus un timeout sur le jeton, et en gérant une exception sur les jetons périmés.

    contournement (workaround)
    Pour bien faire, Il faudrait au maximum placer les opérations "atomiques" côté serveur afin d'éviter la synchronisation côté client.

    Dans l'exemple donné: si le service attendu est l'obtention d'un message unique en fonction d'un nom, il faudrait une seule méthode serveur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class HelloImpl implements HelloInterface{
    public synchronized void getMessage(String name){
      // en supposant qu'on a besoin de garder le dernier "name" appellé, justifiant ainsi de conserver la valeur et de synchroniser
      setName(name);
      return getFullMessage();
    }
    ...
    }

Discussions similaires

  1. RMI synchronisation appels distants
    Par on2101 dans le forum Débuter avec Java
    Réponses: 1
    Dernier message: 04/01/2010, 18h12
  2. [RMI] Impossible de lancer mon serveur
    Par Dahu dans le forum API standards et tierces
    Réponses: 11
    Dernier message: 11/06/2006, 09h17
  3. [RMI] RMI et sérialisation
    Par Arno83 dans le forum Entrée/Sortie
    Réponses: 3
    Dernier message: 11/03/2006, 18h34
  4. [Info] Socket vs RMI
    Par Erok dans le forum API standards et tierces
    Réponses: 11
    Dernier message: 18/05/2004, 16h00
  5. [rmi] Comment exécuter rmic sous Jbuilder9
    Par ensi dans le forum JBuilder
    Réponses: 4
    Dernier message: 27/03/2004, 09h09

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