6
votes

Java Rmi et questions de synchronisation de fil

J'ai réellement deux questions sur Java RMI et Synchronisation de fil:

1) Si je implique mes méthodes distantes RMI telles que synchronisées, sont-ils garantis pour être mutuellement exclusifs? Je dois m'assurer que pas deux de mes méthodes de RMI (méthodes proposées aux clients) s'exécutent en même temps.

2) J'ai une méthode que le serveur exécute périodiquement. Il est utilisé pour faire des nettoyages. Je dois m'assurer que cette méthode particulière n'exécute pas lorsqu'il y a une méthode RMI exécutée / utilisée par des clients distants. De plus, lorsque cette méthode est en cours d'exécution, les appels RMI ne devraient pas être possibles. C'est à dire. Les clients doivent attendre. Avez-vous une idée de la façon dont je peux faire ça? J'ai lu des serrures, mais je ne sais pas comment les utiliser dans ce scénario.

J'ai envisagé de mettre en œuvre des méthodes de RMI en tant que statique et y compris cette méthode de nettoyage à l'intérieur de l'interface RMI, mais il ne semble pas être un moyen élégant de résoudre le problème.

J'ai également écrit la méthode de nettoyage à l'intérieur de l'interface RMI comme synchronisée. Quand je l'ai couru pour tester, il ne semblait pas être des collisions entre méthodes, mais je ne peux pas être sûr.

Merci pour votre temps et vos réponses.


1 commentaires

Si quelque chose posté par Ewernli ou moi était utile, donnez au moins un uppote ;-)


4 Réponses :


11
votes

1) Si je couche ma télécommande RMI méthodes comme synchronisées, sont-ils Garanti d'être mutuellement exclusif? je besoin de s'assurer que pas deux de mes Méthodes de RMI (méthodes offertes à clients) exécuter en même temps.

RMI ne fournit pas une telle garantie à sa propre garantie (contrairement à l'EJB) et deux appels sur le même objet distant peuvent être exécutés simultanément à moins que vous n'ayez mis en œuvre une synchronisation. Votre approche est correcte et la synchronisation de toutes les méthodes garantira en effet qu'aucun deux d'entre eux ne fonctionne en même temps sur le même objet. Remarque: le mot clé synchronisé seul est équivalent à synchronisé (this) .

2) J'ai une méthode que le serveur exécute périodiquement. Il est utilisé pour faire des nettoyages. Je dois m'assurer que Cette méthode particulière ne fait pas Exécuter quand il y a une méthode RMI être exécuté / utilisé par les clients distants.

Si le travail de nettoyage est dans une autre classe, vous devrez définir un verrou que vous partagerez entre l'objet distant et le travail de nettoyage. Dans l'objet distant, définissez une variable d'instance que vous utiliserez comme une serrure. xxx

par convention, les gens utilisent un objet à cette fin. Ensuite, vous devez saisir la serrure dans votre travail périodique avec synchronisé (distanceobj.lock) {...} , en supposant que c'est dans le même package.

Les autres méthodes de la L'objet distant devra être synchronisé de la même manière ( synchronisé seul ne suffit pas), de sorte que les appels de méthode à distance et le travail périodique sont à la fois exclusifs.

J'ai envisagé d'implémenter RMI méthodes comme statique et comprenant que Méthode de nettoyage à l'intérieur du RMI interface, mais cela ne semble pas être un moyen élégant de résoudre le problème.

J'ai aussi écrit la méthode de nettoyage à l'intérieur de l'interface RMI comme synchronisé. Quand je l'ai couru pour tests, il ne semble pas être collisions entre méthodes, mais je ne peut pas être sûr.

Si je comprends bien, vous souhaitez que la logique de nettoyage soit une méthode statique? Une méthode statique avec synchronisé seul attrape une serrure sur la classe. Une méthode "régulière" avec synchronisé attrape une serrure de l'instance d'objet. Ce ne sont pas les mêmes serrures implicites!

mais si vous n'avez que un objet distant instancié, vous pouvez rendre la verrouiller statique (c'est la même que Verrouillage sur la classe, mais est un peu plus propre). Le code de nettoyage peut ensuite être statique et être dans la même classe que l'objet distant ou non.

squelette: xxx


9 commentaires

Je ne sais pas sur le bowvote. Quoi qu'il en soit, pouvez-vous s'il vous plaît élaborer plus sur le mécanisme de verrouillage? Je vois une référence dans une autre réponse et je ne comprenais pas tout cela. Si je mettez en place la serrure d'un objet distant, comment puis-je acquérir le verrou d'un objet local serveur? Quelque chose comme une variable statique publique dans l'objet distant? Ou si vous pouviez fournir des liens / des didacticiels / des extraits de code, ce serait OK aussi. Merci. :)


'RMI ne fournit pas une telle garantie.' Vrai mais ce n'était pas la question. Il synchronise. La synchronisation fournit cette garantie.


Et la synchronisation de toutes les méthodes fonctionnerait tout aussi bien qu'un objet de verrouillage sur les preuves que nous avons été données.


C'est ce que j'ai besoin de confirmer EJP. Si je implémente toutes les méthodes de l'interface RMI comme synchronisée, puis-je être sûr que deux d'entre eux vont courir en même temps à tout moment?


@EJP merci pour l'explication. J'ai édité ma réponse. J'espère que c'est mieux maintenant.


@ Inf.s: Synchronisation Les méthodes garantissent qu'aucun deux d'entre eux ne fonctionne en même temps sur l'objet même . Si c'est suffisant dépendra de la manière dont vous implémentez la logique de nettoyage: dans une classe distincte ou non, comme une méthode statique ou non. Je propose que vous utilisiez une serrure statique.


Après avoir lu votre solution, je envisage de mettre en œuvre le code de nettoyage dans la même classe que l'objet distant, mais pas comme statique. Le code de nettoyage ne sera pas dans l'interface distante, de sorte que les clients ne le sauront pas. Lorsque je suis instanciant de l'objet distant pour RMI, je peux utiliser cette même variable pour appeler le code de nettoyage lorsque j'ai besoin. Je crois que cela devrait être suffisant pour que mon code de nettoyage et mes méthodes appelables client ne fonctionnent pas en même temps. Vos opinions à ce sujet?


C'est bon aussi. Ensuite, synchroniser toutes les méthodes avec synchronisées suffit.


Jetez un coup d'œil à cette question: Stackoverflow.com/questions/3507253 . Si ce que j'ai écrit, il est vrai qu'il peut s'agir d'une bonne raison pour les bowvotes. J'espère vraiment avoir votre opinion à ce sujet.



2
votes
  1. Pour chaque appel d'un client RMI, le serveur RMI exécutera l'appel dans un nouveau fil. Vous n'avez besoin que de synchroniser l'accès aux objets partagés. P> li>

  2. Un autre thread ou minuterie n'empêchera pas votre serveur d'accepter des appels du côté du client. Cette synchronisation doit être synchronisée, la meilleure pratique dépend de la durée pendant laquelle le travail de nettoyage peut-il être interrompu ou serait-il possible de mettre les demandes dans une file d'attente, etc. Le moyen le plus simple serait de laisser les méthodes RMI attendre la serrure comme décrit déjà par Ewernli. P> Li>

    Edit: Selon votre commentaire, un squelette qui démontre comment réaliser ce type de synchronisation de base. Comme tout est maintenant mutuellement exclusif, vous ne pouvez pas vous attendre à des performances élevées avec de multiples clients impliqués. Quoi qu'il en soit, cela couvrirait vos besoins. (J'espère). Si votre projet pousse, vous devriez lire le tutoriel de concurrence P >

    Object mutex = new Object();
    
    int rmiMethod1() {
        synchronized (mutex) {
            doWhatNeeded1();
        }
    }
    
    int rmiMethod2() {
        synchronized (mutex) {
            doWhatNeeded2();
        }
    }
    
    // in your cleanup thread
    void run() {
        synchronized (mutex) {
            cleanUp();
        }
    }
    

6 commentaires

Je sais que RMI exécute de nouveaux appels dans de nouveaux threads. Le problème est que je ne veux pas que deux méthodes distantes fonctionnent en même temps. Cela inclut la même méthode qui ne s'appelle pas plus d'une fois. Je pensais que simplement utiliser des méthodes synchronisées résoudrait le problème. J'ai lu cela hors du forum grâce à la recherche de Google. Est-ce une certitude que RMI ignorera la directive synchronisée et procédera à des méthodes distantes simultanément?


Merci pour vous pour cet exemple de très illustratif. À propos de l'objet mutex. Synchronisé (MuTex): Que fait cette ligne? Acquérit-il le verrou fourni pour l'objet? En outre, pourquoi ne pas utiliser un objet de verrouillage comme indiqué dans le tutoriel de la concurrence? Merci.


Synchronisé (Mutex) tente d'accueillir un moniteur ainsi appelé moniteur qui garantit qu'un seul fil entre dans la section critique (protégée). Si un autre thread est déjà entré dans la section critique, toutes les autres doivent attendre jusqu'à ce qu'il quitte le bloc Synchronisé {}. Les moyens possibles de le faire sont décrits dans le tutoriel. Celui-ci est ma préférence personnelle.


(1) n'est pas correct. Premièrement, le comportement de threading de RMI est délibérément et explicitement non spécifié. Deuxièmement, dans la mise en œuvre du soleil, la mise en commun de la connexion peut signifier que les appels successifs du même client sont exécutés dans le même fil. Le code indiqué est équivalent à la synchronisation des méthodes concernées, ce qui serait beaucoup plus simple.


@EJP HM, je lisais cela à nouveau après des années. J'ai probablement essayé de décrire le comportement que j'ai observé dans un système que j'ai dû conserver de temps en temps.


@staquette Si les appels d'un client d'un client avaient plus de 15 ans, ils s'exécutent tous dans de nouveaux threads de serveur. Mais rien de tout cela n'est spécifié nulle part, délibérément.



-1
votes

Vous devez garder à l'esprit que RMI crée l'illusion d'un "objet distant", mais il n'ya pas moins de trois objets: le talon local, le squelette distant et l'objet distant réel. En tant que compromis de la conception, cette illusion est pas complète et verrouille seul le talon local . Il n'y a pas de synchronisation sur le réseau. Recherchez sur Internet pour RMI + Stub + Synchronisé et vous trouverez de nombreuses explications, comme par exemple celle-ci:

Méthodes Java RMI et synchronisées

Vous devez donc implémenter une sorte de synchronisation non-RMI, purement du côté serveur vous-même. Ensuite, vous pouvez appeler ces verrouillages pure serveur de vos méthodes distantes; Mais vous avez besoin du niveau supplémentaire d'indirection.

Pour tester votre code, le plus facile est de mettre en pause vos threads sous un bon débogueur comme Eclipse. Eclipse vous montrera clairement que le thread en pause contient le blocage du blocage quels autre thread (s).


4 commentaires

Il n'y a pas eu de squelettes depuis 1998.


Voulez-vous dire "depuis Java 1998"? Plus sérieusement: Oui, les squelettes de compilation ont été remplacés par un équivalent de temps d'exécution. Est-ce de toute pertinence pour cette page? J'en doute.


Je voulais dire ce que j'ai écrit, et s'il y a une blague, je ne l'obtiens pas. Si ce n'est pas pertinent pour cette réponse, vous devez le supprimer de cette réponse. Le reste est bon.


Et ce que 'ne bloque que le talon local?



0
votes

Pour clarifier toute cette confusion:

  1. Si vous synchronisez vos implémentations de méthode distante, un seul client peut être exécuté à la fois.

  2. Si vous synchronisez votre tâche de nettoyage sur l'objet distant, il rejoint (1).

  3. Vous ne pouvez pas définir des méthodes distantes comme statique.


0 commentaires