Processus Erlang vs thread Java

Je Lis Le Livre" Elixir en Action " de Saša Jurić, et dans le premier chapitre il est dit:

Les processus Erlang sont complètement isolés les uns des autres. Ils partagent pas de mémoire, et un plantage d'un processus ne provoque pas un plantage d'autres processus.

N'est-ce pas aussi vrai pour les threads Java? Je veux dire quand le thread Java se bloque, il ne plante pas non plus les autres threads-en particulier, si nous regardons les threads de traitement des requêtes (excluons le thread main de cette discussion)

53
demandé sur Wand Maker 2015-08-30 10:43:47

6 réponses

Répétez après moi: "ce sont des paradigmes différents"

Dites cela à haute voix 20 fois ou plus -- c'est notre mantra pour le moment.

Si nous devons vraiment comparer les pommes et les oranges, considérons au moins où se croisent les aspects communs du "fruit".

Les "objets" Java sont l'Unité de calcul de base D'un programmeur Java. C'est-à-dire un objet (fondamentalement une structure avec des bras et des jambes qui a une encapsulation un peu plus strictement appliquée que dans C++) est l'outil principal avec lequel vous modélisez le monde. Vous pensez que " cet objet sait / a {[0] } et exécute Functions {A(),B(),C()} dessus, porte le Data partout où il va, et peut communiquer avec d'autres objets en appelant des fonctions / méthodes définies dans le cadre de leur interface publique. C'est un nom, et ce nom ne trucs.". C'est-à-dire, vous orientez votre processus de pensée autour de ces unités de calcul. Le cas par défaut est que les choses qui se produisent parmi les objets se produisent dans séquence, et un crash interrompt cette séquence. Ils sont appelés " objets "et par conséquent (si nous ignorons la signification originale D'Alan Kay) nous obtenons"l'orientation de l'objet".

Les "processus" Erlang sont l'Unité de calcul de base D'un programmeur Erlang. Un processus (essentiellement un programme séquentiel autonome fonctionnant dans son propre temps et dans son propre espace) est l'outil principal avec lequel un Erlanger modélise le Monde(1). Similaire à la façon dont les objets Java définissent un niveau d'encapsulation, les processus Erlang définissent également le niveau d'encapsulation, mais dans le cas d'Erlang les unités de calcul sont complètement coupés l'un de l'autre. Vous ne pouvez pas appeler une méthode ou une fonction sur un autre processus, ni accéder à des données qui s'y trouvent, ni même exécuter un processus dans le même contexte de synchronisation que les autres processus, et il n'y a aucune garantie sur l'ordre de réception des messages par rapport aux autres processus qui peuvent envoyer des messages. Ils peuvent aussi bien être sur différentes planètes entièrement (et, à bien y penser, c'est en fait plausible). Ils peuvent se bloquer indépendamment les uns des autres et les autres processus ne sont impactés que s'ils ont délibérément choisi d'être impactés (et même cela implique la messagerie: essentiellement s'inscrire pour recevoir une note de suicide du processus Mort qui n'est pas garanti d'arriver dans un ordre quelconque par rapport au système dans son ensemble, auquel vous pouvez

Java traite de la complexité directement dans algorithmes composés: comment les objets travaillent ensemble pour résoudre un problème. Il est conçu pour le faire dans un contexte d'exécution unique, et le cas par défaut en Java est l'exécution séquentielle. Plusieurs threads en Java indiquent plusieurs contextes d'exécution et est un sujet très complexe en raison de l'activité d'impact dans différents contextes de synchronisation ont les uns sur les autres (et le système dans son ensemble: donc la programmation défensive, les schémas d'exception, etc.). Dire "multi-thread" en Java signifie quelque chose différent qu'en Erlang, en fait, ce n'est jamais dit même en Erlang parce que c'est toujours le cas de base. Notez ici que les threads Java impliquent une ségrégation en ce qui concerne le temps, pas la mémoire ou les références visibles-la visibilité en Java est contrôlée manuellement en choisissant ce qui est privé et ce qui est public; les éléments universellement accessibles d'un système doivent être conçus pour être "threadsafe" et réentrants, séquentialisés via des mécanismes de file d'attente, ou En bref: la planification d' est un problème géré manuellement dans les programmes Java threadés / simultanés.

Erlang sépare le contexte d'exécution de chaque processus en termes de calendrier d'exécution (planification), d'accès à la mémoire et de visibilité de référence et simplifie ainsi chaque composant d'un algorithme en l'isolant complètement . Ce n'est pas seulement le cas par défaut, c'est le seul cas disponible sous ce modèle de calcul. Cela se fait au prix de ne jamais connaître exactement la séquence d'une opération donnée une fois une partie de vos séquences de traitement traverse une barrière de message-parce que les messages sont tous essentiellement des protocoles réseau et qu'il n'y a pas d'appels de méthode qui peuvent être garantis pour s'exécuter dans un contexte donné. Cela serait analogue à la création d'une instance JVM par objet, et leur permettant seulement de communiquer entre les sockets - ce serait ridiculement lourd en Java, mais C'est la façon dont Erlang est conçu pour fonctionner (incidemment, c'est aussi la base du concept d'écriture " Java microservices " si l'on abandonne le bagage orienté web, le mot à la mode a tendance à impliquer-les programmes Erlang sont, par défaut, des essaims de microservices). Son tout sur les compromis.

Ce sont des paradigmes différents. Le point commun le plus proche que nous pouvons trouver est de dire que du point de vue du programmeur, les processus Erlang sont analogues aux objets Java. Si nous devons trouver quelque chose à comparer les threads Java... Eh bien, nous n'allons tout simplement pas trouver quelque chose comme ça à Erlang, parce qu'il n'y en a pas concept comparable à Erlang. Battre un cheval mort: ce sont des paradigmes différents . Si vous écrivez quelques programmes non triviaux dans Erlang, cela deviendra facilement évident.

Notez que je dis "ce sont des paradigmes différents" mais n'ont même pas touché le sujet de la POO vs FP. La différence entre "penser en Java" et "penser en Erlang" est plus fondamentale que la POO vs FP.

S'il est vrai que la fondation "concurrency oriented" ou "process oriented" D'Erlang est plus près de ce que Alan Kay avait en tête lorsqu'il a inventé le terme "orienté objet" (2), ce n'est pas vraiment le point ici. Ce que Kay voulait dire, c'est que l'on peut réduire la complexité cognitive d'un système en coupant vos computrons en morceaux discrets, et l'isolement est nécessaire pour cela. Java accomplit cela d'une manière qui le laisse encore fondamentalement procédural dans la nature, mais structure le code autour d'une syntaxe spéciale sur des fermetures de répartition d'ordre supérieur appelées "définitions de classe". Erlang cela se fait en divisant le contexte en cours d'exécution par objet. Cela signifie que les thingies Erlang ne peuvent pas appeler les méthodes les unes sur les autres, mais les Thingies Java Le peuvent. Cela signifie que les choses Erlang peuvent se bloquer isolément mais que les choses Java ne le peuvent pas. un grand nombre d'implications découlent de cette différence fondamentale-d'où des "paradigmes différents". Compromis.


Notes de bas de Page:

  1. , Incidemment, Erlang implémente une version de "l'acteur modèle", mais nous n'utiliserons pas cette terminologie comme Erlang est antérieure à la vulgarisation de ce modèle. Joe ne le savait pas quand il a conçu Erlang et a écrit sa thèse .
  2. Alan Kay a dit un peu sur Ce qu'il voulait dire quand il a inventé le terme "orienté objet", le plus intéressant étant sa prise sur la messagerie (notification unidirectionnelle d'un processus indépendant avec son propre timing et sa propre mémoire à l'autre) VS appels (appels de fonction ou de méthode dans un contexte les lignes floutent un peu entre l'interface de programmation présentée par le langage de programmation et l'implémentation ci-dessous.
82
répondu zxq9 2017-10-10 06:21:40

Certainement pas. Tous les threads en Java partagent le même espace d'adressage, il est donc possible pour un thread de détruire des choses appartenant à un autre thread. Dans la machine virtuelle Erlang, cela n'est tout simplement pas possible car chaque processus est isolé de tous les autres. C'est le point de l'ensemble d'entre eux. Chaque fois que vous voulez qu'un processus fasse quelque chose avec des données d'un autre, votre code doit envoyer un message à l'autre processus. Les seules choses partagées entre les processus sont de grands objets binaires et ceux-ci sont immuables.

16
répondu Daniel 2015-08-30 08:10:48

Les processus Java peuvent en fait partager de la mémoire. Par exemple, vous pouvez passer la même instance à deux threads distincts et les deux peuvent manipuler son état, ce qui entraîne des problèmes potentiels tels que blocages.

Elixir / Erlang d'autre part aborde cela par le concept d'immuabilité, donc quand vous passez quelque chose à un processus, ce sera une copie de la valeur d'origine.

15
répondu Patrick Oscity 2015-08-30 08:08:32

Lorsque le thread Java meurt, il n'a pas non plus d'impact sur les autres threads

Permettez-moi de poser une contre-question: Pourquoi pensez-vous que Thread.stop() est obsolète depuis plus d'une décennie? La raison en est précisément la négation de votre déclaration ci-dessus.

Pour donner deux exemples spécifiques: vous stop() un thread alors qu'il exécute quelque chose d'aussi inoffensif que System.out.println() ou Math.random(). Résultat: ces deux fonctionnalités sont maintenant cassées pour l'ensemble de la JVM. La même chose s'applique à tout autre code synchronisé votre application peut s'exécuter.

Si nous regardons les threads de traitement des requêtes

L'application peut théoriquement être codée de telle sorte qu'aucune ressource partagée protégée par des verrous n'est jamais utilisée; cependant, cela aidera seulement à souligner la mesure exacte dans laquelle les threads Java sont codépendants. Et l '"indépendance" obtenue ne concernera que les threads de traitement des requêtes, pas tous les threads dans une telle application.

4
répondu Marko Topolnik 2015-08-30 09:40:08

Pour compléter les réponses précédentes, les threads Java ont deux types: daemon et non daemon.

Pour changer le type d'un thread, vous pouvez appeler .setDaemon(boolean on). La différence est qu'un thread démon n'empêche pas la JVM de quitter. Comme le dit Javadoc for Thread:

La Machine virtuelle Java se ferme lorsque les seuls threads en cours d'exécution sont tous les threads du démon.

Cela signifie: les threads utilisateur (ceux qui ne sont pas spécifiquement définis pour être démon) gardent la JVM de la résiliation. D'un autre côté, les threads du démon peuvent être en cours d'exécution lorsque tous les threads non-démon sont terminés, auquel cas la JVM quittera. Donc, pour répondre à votre question: vous pouvez démarrer un thread qui ne quitte pas la JVM quand il se termine.

Quant à la comparaison avec Erlang/Elixir, n'oubliez pas: Ce sont des paradigmes différents, comme déjà mentionné.

Il n'est pas impossible pour la JVM d'imiter le comportement D'Erlang bien que ce ne soit pas pour ce à quoi elle était destinée et, par conséquent, elle va avec beaucoup de compromis. Les projets suivants tentent d'y parvenir:

2
répondu Olinasc 2015-08-31 13:55:31

N'est-ce pas aussi vrai pour les threads Java? Je veux dire quand le thread Java se bloque, il ne plante pas non plus les autres threads

Oui et non. J'explique:

  • Se référant à la mémoire partagée: différents threads dans un processus Java partagent l'ensemble du tas, donc les threads peuvent interagir dans un grand nombre de manières planifiées et non planifiées. cependant les objets dans la pile (par exemple un contexte que vous transmettez à la méthode appelée) ou un ThreadLocal sont leurs propres threads (à moins qu'ils ne démarrent le partage de références).

  • Plantage: si un thread se bloque en Java (un Throwable est propagé dans Thread.run(), ou si quelque chose est bouclé ou bloqué), cet incident peut ne pas affecter les autres threads (par exemple, un pool de connexions dans un serveur continuera à fonctionner). cependant {[13] } Comme différents threads interagissent. D'autres threads seront facilement bloqués si l'un d'eux se termine anormalement (par exemple, un thread essayant de lire à partir d'un tuyau vide à partir d'un autre thread qui n'a pas fermé son extrémité). Donc, à moins que les développeurs sont très paranoïaque attention, il est très probable que les effets secondaires se produisent.

Je doute que tout autre paradigme ait l'intention de fonctionner comme des Îles totalement indépendantes. Ils doivent partager l'information et coordonner d'une manière ou d'une autre. Et puis il y aura la chance de gâcher les choses. C'est juste qu'ils adopteront une approche plus défensive qui " vous donne moins de corde pour vous accrocher "(même idiome qu'avec les pointeurs).

1
répondu Javier 2015-09-03 14:47:40