Que peuvent faire plusieurs threads qu'un seul thread ne peut pas? [fermé]

100

Bien que les threads puissent accélérer l'exécution du code, sont-ils réellement nécessaires? Est-ce que chaque morceau de code peut être fait en utilisant un seul thread ou existe-t-il quelque chose d'existant qui ne peut être accompli qu'en utilisant plusieurs threads?

Oiseau en colère
la source
29
Sur la base de certaines des réponses déjà publiées ici, je pense que des éclaircissements sont nécessaires. Le filetage a pour but de permettre aux ordinateurs de (sembler) faire plus d’une chose à la fois. Si cela est fait en utilisant un ordinateur avec un seul noyau, vous ne verrez aucune accélération globale. Ce que vous allez voir, c'est débloquer. Dans un programme à un seul thread, l'interface utilisateur se bloque pendant les calculs. Dans un programme multithread, l'interface utilisateur peut toujours être utilisable pendant que les calculs ont lieu en arrière-plan.
Robert Harvey
11
Bien sûr, si vous avez plusieurs cœurs de processeur de votre ordinateur ( ce qui est monnaie courante de nos jours), votre programme peut utiliser des threads pour tirer profit des cœurs supplémentaires pour effectuer votre traitement, et vous verrez un gain de vitesse, parce que vous jetez plus de puissance à votre problème informatique. Si vous n'utilisez pas du tout de threads, votre programme n'utilisera qu'un seul cœur de processeur, ce qui est bien si c'est tout ce dont vous avez besoin.
Robert Harvey
14
Un programme à un seul thread ne peut pas bloquer les ressources de la même manière qu'un programme à plusieurs threads.
zzzzBov
3
Réponse: courir sur deux noyaux
Daniel Little
6
Réponse: provoquer une impasse.
Job

Réponses:

111

Tout d'abord, les threads ne peuvent pas accélérer l'exécution du code. Ils ne rendent pas l'ordinateur plus rapide. Tout ce qu'ils peuvent faire, c'est augmenter l'efficacité de l'ordinateur en utilisant du temps qui serait autrement perdu. Dans certains types de traitement, cette optimisation peut augmenter l'efficacité et réduire le temps d'exécution.

La réponse simple est oui. Vous pouvez écrire n'importe quel code à exécuter sur un seul thread. Preuve: Un système à processeur unique ne peut exécuter des instructions que de manière linéaire. L'exécution de plusieurs lignes est effectuée par le système d'exploitation, qui enregistre les interruptions, enregistre l'état du thread en cours et en démarre un autre.

La réponse complexe est ... plus complexe! La raison pour laquelle les programmes multithread peuvent souvent être plus efficaces que les programmes linéaires est un "problème" matériel. La CPU peut exécuter des calculs plus rapidement que la mémoire et les entrées / sorties de stockage. Ainsi, une instruction "add", par exemple, s'exécute beaucoup plus rapidement qu'un "fetch". Les caches et l'extraction d'instructions de programme dédiées (pas sûr du terme exact ici) peuvent combattre cela dans une certaine mesure, mais le problème de la vitesse reste.

Le thread est un moyen de lutter contre cette non-concordance en utilisant le processeur pour obtenir des instructions liées au processeur pendant l'exécution des instructions d'entrée-sortie. Un plan d’exécution de threads typique serait probablement: récupérer des données, traiter des données, écrire des données. Supposons que l'extraction et l'écriture prennent 3 cycles et que le traitement en nécessite un, à des fins d'illustration. Vous pouvez voir que pendant que l'ordinateur lit ou écrit, il ne fait rien pendant 2 cycles chacun? Il est clair que nous sommes paresseux et nous devons craquer notre fouet d'optimisation!

Nous pouvons réécrire le processus en utilisant le threading pour utiliser ce temps perdu:

  1. N ° 1 chercher
  2. pas d'opération
  3. # 2 chercher
  4. # 1 est terminé, traitez-le
  5. écrire n ° 1
  6. N ° 1 chercher
  7. # 2 est terminé, traitez-le
  8. écrire n ° 2
  9. chercher # 2

Etc. Évidemment, ceci est un exemple quelque peu artificiel, mais vous pouvez voir comment cette technique peut utiliser le temps qui serait autrement passé à attendre IO.

Notez que le threading présenté ci-dessus ne peut qu'accroître l'efficacité sur les processus fortement liés à l'IO. Si un programme calcule principalement des choses, il ne va pas y avoir beaucoup de "trous" dans lesquels nous pourrions faire plus de travail. En outre, il y a une surcharge de plusieurs instructions lors du changement de thread. Si vous exécutez trop de threads, le processeur passera la majeure partie de son temps à basculer et à ne pas trop travailler sur le problème. C'est ce qu'on appelle la raclée .

Tout cela va bien pour un processeur simple cœur, mais la plupart des processeurs modernes ont deux cœurs ou plus. Les threads ont toujours le même objectif - optimiser l'utilisation du processeur, mais cette fois, nous avons la possibilité d'exécuter deux instructions distinctes en même temps. Cela peut réduire le temps d'exécution d'un facteur égal au nombre de cœurs disponibles, car l'ordinateur est multitâche, et non un changement de contexte.

Avec plusieurs cœurs, les threads fournissent une méthode de division du travail entre les deux cœurs. Ce qui précède s'applique toujours à chaque noyau individuel; Un programme qui fonctionne au maximum avec deux threads sur un même cœur fonctionnera probablement avec une efficacité maximale avec environ quatre threads sur deux cœurs. (L'efficacité est mesurée ici par le nombre minimum d'exécutions d'instructions NOP.)

Les problèmes d'exécution de threads sur plusieurs cœurs (par opposition à un seul) sont généralement pris en charge par le matériel. Le CPU s'assurera qu'il verrouille les emplacements de mémoire appropriés avant de le lire / écrire. (J'ai lu qu'il utilise un bit de drapeau spécial en mémoire pour cela, mais cela peut être accompli de plusieurs façons.) En tant que programmeur utilisant des langages de niveau supérieur, vous n'avez plus à vous soucier de quoi que ce soit sur deux cœurs. aurait à un.

TL; DR: les threads peuvent fractionner le travail pour permettre à l'ordinateur de traiter plusieurs tâches de manière asynchrone. Cela permet à l'ordinateur de fonctionner avec une efficacité maximale en utilisant tout le temps de traitement disponible, plutôt que de le verrouiller lorsqu'un processus attend une ressource.

Michael K
la source
17
Excellente réponse. Je voulais juste préciser que , après un certain point, l' ajout de threads peut réellement faire une course de programme plus lent , parce que tous les précédemment « gaspillé » le temps est utilisé, et vous êtes maintenant ne fait qu'ajouter changement de contexte supplémentaire et les frais généraux de synchronisation.
Karl Bielefeldt
8
+1 pour décrire comment les threads aident au traitement du blocage des entrées / sorties. Une autre utilisation des threads est de permettre à l'interface utilisateur de continuer à traiter les actions de l'utilisateur (mouvement de la souris, barres de progression, frappes au clavier) de sorte que l'utilisateur ait la perception que le programme n'est pas "gelé".
jqa
3
Encore un ajout: à proprement parler, les threads n’ajoutent aucune expressivité à la plupart des langues; vous pourriez, si cela était absolument nécessaire, mettre en œuvre vous-même le multiplexage et obtenir les mêmes résultats. En pratique, cependant, cela reviendrait à réimplémenter toute votre bibliothèque de threads - tout comme la récursion n'est pas strictement nécessaire, mais peut être émulée en écrivant votre propre pile d'appels.
Kilian Foth
9
@ james: Je classerais le traitement de l'interface utilisateur comme une autre forme d'E / S. Peut-être le pire, car les utilisateurs ont tendance à être lents et non linéaires. :)
TMN
7
Il y a une hypothèse silencieuse dans la question et la réponse autour de l'ordinateur étant un cœur ou un processeur. Ma montre a deux cœurs, je doute que cette hypothèse soit valable sur toutes les machines modernes.
blueberryfields
37

Que peuvent faire plusieurs threads qu'un seul thread ne peut pas?

Rien.

Esquisse d'épreuve simple:

  • [Conjecture église-Turing] ⇒ Tout ce qui peut être calculé peut être calculé par une machine de Turing universelle.
  • Une machine de turing universelle est mono-thread.
  • Ainsi, tout ce qui peut être calculé peut être calculé par un seul thread.

Notez, cependant, qu'il y a une grosse hypothèse cachée dedans: à savoir que le langage utilisé dans le seul thread est Turing-complete.

Donc, la question plus intéressante serait la suivante: « Peut ajouter que le multi-threading à un langage complet non Turing faire Turing-complet? » Et je crois que la réponse est "oui".

Prenons Total des langages fonctionnels. [Pour ceux qui ne sont pas familiers: tout comme la programmation fonctionnelle consiste à programmer avec des fonctions, la programmation fonctionnelle totale consiste à programmer avec des fonctions totales.]

Le total des langages fonctionnels n'est évidemment pas complet avec Turing: vous ne pouvez pas écrire une boucle infinie dans un TFPL (en fait, c'est à peu près la définition de "total"), mais vous pouvez le faire dans une machine de Turing, car il existe au moins un programme qui ne peut pas être écrit dans un TFPL mais peut le être dans un UTM. Par conséquent, les TFPL sont moins puissants en calcul que les UTM.

Cependant, dès que vous ajoutez des threads à un TFPL, vous obtenez des boucles infinies: faites juste chaque itération de la boucle dans un nouveau thread. Chaque thread individuel renvoie toujours un résultat. Il s'agit donc de Total, mais chaque thread génère également un nouveau thread qui exécute la prochaine itération, à l'infini.

Je pense que cette langue serait Turing-complète.

À tout le moins, cela répond à la question initiale:

Que peuvent faire plusieurs threads qu'un seul thread ne peut pas?

Si vous avez un langage qui ne peut pas faire de boucles infinies, le multi-threading vous permet de faire des boucles infinies.

Notez, bien sûr, que la création d'un fil est un effet secondaire et que notre langage étendu n'est donc pas seulement Total, il n'est même plus fonctionnel.

Jörg W Mittag
la source
13
Depuis que vous avez évoqué une "preuve", je ne peux pas m'empêcher de "bien, en fait ...". Je pense que vous abusez de la notion de calculabilité. La preuve est une chose mignonne et je comprends votre point de vue, mais ce n'est pas vraiment au bon niveau d'abstraction. Ne pas être capable de faire des choses n’est pas la même chose que de ne pas pouvoir calculer , par exemple, vous ne pouvez pas utiliser votre preuve, car la machine de Turing peut calculer "chaque fonction calculable", elle peut le faire en 3 secondes. À proprement parler, une seule machine à threads sans interruptions ne peut pas accéder aux E / S tout en gardant son processeur occupé à effectuer des calculs.
xmm0
1
Et, aucun ordinateur réel n'est une machine de Turing.
Jens
1
@ColeJohnson: Une impasse est un détail de la mise en œuvre. La sortie visible est "ne s'arrête pas", ce qui est facilement réalisable avec un seul thread.
Heinzi
1
@Heinzi: "facilement faisable" est un euphémisme. Si je me souviens bien, le deuxième ou le troisième programme que je jamais écrit a fait exactement cela! ;-)
Joachim Sauer le
1
Si l'univers est ed single thread , alors quelle est la théorie des cordes ? Vous ne pouvez pas discuter avec la science comme ça.
CorsiKa
22

En théorie, tout ce qu'un programme multithread peut faire peut également être fait avec un programme à un seul thread, mais juste plus lentement.

En pratique, la différence de vitesse peut être si grande qu'il est impossible d'utiliser un programme à un seul thread pour la tâche. Par exemple, si un travail de traitement de données par lots est exécuté toutes les nuits et qu'il faut plus de 24 heures pour terminer un seul thread, vous n'avez pas d'autre choix que de le rendre multithread. (En pratique, le seuil est probablement encore plus bas: souvent, ces tâches de mise à jour doivent être terminées tôt le matin, avant que les utilisateurs ne puissent recommencer à utiliser le système. En outre, d'autres tâches peuvent dépendre d'elles, qui doivent également s'achever dans la même nuit. La durée d’utilisation disponible peut être aussi basse que quelques heures / minutes.)

Faire du travail informatique sur plusieurs threads est une forme de traitement distribué; vous distribuez le travail sur plusieurs threads. L'économiseur d'écran SETI est un autre exemple de traitement distribué (utilisant plusieurs ordinateurs au lieu de plusieurs threads): il faudrait beaucoup de temps pour traiter autant de données de mesure sur un seul processeur et les chercheurs préféreraient voir les résultats avant la retraite ;-) ne disposant pas du budget nécessaire pour louer un superordinateur aussi longtemps, ils répartissent le travail sur des millions d'ordinateurs personnels pour le rendre moins cher.

Péter Török
la source
L'économiseur d'écran SETI est un exemple de thread en ce sens qu'il s'exécute sur un thread en arrière-plan de votre ordinateur; vous pouvez toujours faire d'autres choses sur votre ordinateur pendant qu'il traite des données en arrière-plan. Sans le fil, il y aurait une pause pendant que l'économiseur d'écran SETI effectue ses calculs; il faudrait attendre que cela se termine avant de pouvoir continuer votre propre travail.
Robert Harvey
3
@Robert: Je pense que Péter utilise SETI @ Home pour expliquer le concept de la division du travail en plusieurs processeurs. L'informatique distribuée est bien sûr différente du multithreading, mais le concept est similaire.
Steven
5
Je pense que l'exemple de SETI est l'informatique distribuée plutôt que le multi-thread. Des concepts similaires mais pas la même chose.
11

Bien que les threads semblent être un petit pas par rapport au calcul séquentiel, ils représentent en fait un pas énorme. Ils rejettent les propriétés les plus essentielles et les plus attrayantes du calcul séquentiel: la compréhensibilité, la prévisibilité et le déterminisme. Les threads, en tant que modèle de calcul, sont extrêmement non déterministes et le travail du programmeur devient un travail d'élagage que le non déterminisme.

- Le problème des threads (www.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf).

L'utilisation de threads offre certains avantages en termes de performances, car elle permet de répartir le travail sur plusieurs cœurs, mais leur prix est souvent très avantageux.

L’un des inconvénients de l’utilisation de threads qui n’a pas encore été mentionnée est la perte de compartimentalisation des ressources que vous obtenez avec des espaces de processus à thread unique. Par exemple, supposons que vous rencontriez le cas d'une erreur de segmentation. Dans certains cas, il est possible de remédier à cette situation dans une application multi-processus, en laissant simplement l'enfant défaillant mourir et en en reproduisant un nouveau. C'est le cas dans le backend prefork d'Apache. Quand une instance httpd monte en panne, le pire des cas est que la requête HTTP particulière peut être abandonnée pour ce processus, mais Apache génère un nouvel enfant et souvent la requête si elle est simplement renvoyée et traitée. Le résultat final est que Apache dans son ensemble n'est pas détruit avec le thread défectueux.

Une autre considération dans ce scénario concerne les fuites de mémoire. Il existe des cas où vous pouvez gérer avec élégance une panne de thread (sous UNIX, la récupération de signaux spécifiques - même segfault / fpviolation - est possible), mais même dans ce cas, vous avez peut-être perdu toute la mémoire allouée par ce thread. (malloc, nouveau, etc.). Ainsi, même si votre processus est susceptible de continuer à fonctionner, il perd de plus en plus de mémoire avec chaque panne / récupération. Là encore, il existe, dans une certaine mesure, des moyens de minimiser ce problème, comme l'utilisation par Apache de pools de mémoire. Mais cela ne protège toujours pas contre la mémoire qui aurait pu être allouée par des bibliothèques tierces que le thread aurait pu utiliser.

Et, comme l'ont souligné certaines personnes, la compréhension des primitives de synchronisation est peut-être la chose la plus difficile à faire. Ce problème en lui-même - obtenir juste la logique générale correcte pour tout votre code - peut être un casse-tête énorme. De mystérieuses impasses sont susceptibles de se produire aux moments les plus étranges, et parfois même avant que votre programme n'ait été exécuté en production, ce qui rend le débogage d'autant plus difficile. Ajoutez à cela le fait que les primitives de synchronisation varient souvent beaucoup avec la plate-forme (Windows contre POSIX), et que le débogage est souvent plus difficile, ainsi que la possibilité de conditions de concurrence à tout moment (démarrage / initialisation, exécution et arrêt), la programmation avec des threads a vraiment peu de pitié pour les débutants. Et même pour les experts, il y a toujours peu de pitié simplement parce que la connaissance du filetage lui-même ne minimise pas la complexité en général. Chaque ligne de code threadé semble parfois aggraver de manière exponentielle la complexité globale du programme et augmenter la probabilité qu'une impasse cachée ou une situation de concurrence étrange apparaisse à tout moment. Il peut également être très difficile d’écrire des cas de test pour dénicher ces choses.

C'est pourquoi certains projets tels qu'Apache et PostgreSQL sont pour la plupart basés sur des processus. PostgreSQL exécute tous les threads dans un processus séparé. Bien sûr, cela ne résout pas le problème de la synchronisation et des conditions de concurrence, mais cela ajoute un peu de protection et simplifie à certains égards les choses.

Plusieurs processus exécutant chacun un seul thread d'exécution peuvent être bien meilleurs que plusieurs threads exécutés dans un seul processus. Et avec l'avènement de la plupart des nouveaux codes peer-to-peer tels qu'AMQP (RabbitMQ, Qpid, etc.) et ZeroMQ, il est beaucoup plus facile de scinder les threads entre différents espaces de processus et même des machines et des réseaux, ce qui simplifie grandement les choses. Mais quand même, ce n'est pas une solution miracle. Il reste encore une complexité à gérer. Vous déplacez simplement certaines de vos variables de l'espace de processus vers le réseau.

L'essentiel est que la décision d'entrer dans le domaine des threads n'est pas légère. Une fois que vous pénétrez sur ce territoire, presque instantanément, tout devient plus complexe et de nouvelles races de problèmes entrent dans votre vie. Cela peut être amusant et cool, mais c'est comme l'énergie nucléaire: quand les choses tournent mal, elles peuvent aller mal et vite. Je me souviens d'avoir suivi un cours de formation à la criticité il y a de nombreuses années et ils ont montré des photos de scientifiques de Los Alamos qui ont joué avec du plutonium dans les laboratoires de la Seconde Guerre mondiale. Beaucoup prenaient peu ou pas de précautions à prendre en cas d’exposition, et en un clin d’œil - en un éclair, une clarté indolore, tout serait fini pour eux. Quelques jours plus tard, ils étaient morts. Richard Feynman a plus tard qualifié cela de " chatouillant la queue du dragon""C’est un peu ce que peut être le jeu avec les discussions (du moins pour moi en tout cas). Cela semble plutôt inoffensif au début, et quand vous mordez, vous vous grattez la tête à la rapidité avec laquelle les choses se sont détériorées. Mais au moins les discussions ont gagné. ne te tue pas.

Mike Owens
la source
Ma réponse TL; DR n'est rien en comparaison de cette belle pièce sur ce qu'un seul thread ne fera pas pour vous.
bmike
1
Pause café de l'après-midi
Mike Owens
10

Tout d'abord, une application à thread unique ne tirera jamais parti d'un processeur multicœur ou d'un hyper-threading. Cependant, même sur un seul cœur, les processeurs mono-thread faisant du multi-threading présentent des avantages.

Considérez l'alternative et si cela vous rend heureux. Supposons que plusieurs tâches doivent être exécutées simultanément. Par exemple, vous devez continuer à communiquer avec deux systèmes différents. Comment faites-vous cela sans multi-threading? Vous créerez probablement votre propre planificateur et le laisserez appeler les différentes tâches à exécuter. Cela signifie que vous devez diviser vos tâches en plusieurs parties. Vous devez probablement respecter certaines contraintes en temps réel et veiller à ce que vos pièces ne prennent pas trop de temps. Sinon, la minuterie expirera dans d'autres tâches. Cela rend plus difficile le fractionnement d’une tâche. Plus vous avez de tâches à gérer, plus vous devez vous séparer et plus votre ordonnanceur sera complexe pour répondre à toutes les contraintes.

Lorsque vous avez plusieurs threads, la vie peut devenir plus facile. Un planificateur préemptif peut arrêter un thread à tout moment, conserver son état et en redémarrer un autre. Il redémarrera lorsque votre thread aura son tour. Avantages: la complexité de l'écriture d'un planificateur a déjà été effectuée pour vous et vous n'avez pas à diviser vos tâches. En outre, le planificateur est capable de gérer des processus / threads dont vous n'êtes même pas au courant. De plus, lorsqu'un thread n'a rien à faire (il attend un événement), il ne prend aucun cycle de traitement. Ce n'est pas si facile à accomplir lorsque vous créez votre planificateur à thread unique. (endormir quelque chose n'est pas si difficile, mais comment se réveille-t-il?)

L'inconvénient du développement multithread est que vous devez comprendre les problèmes de concurrence, les stratégies de verrouillage, etc. Développer du code multithread sans erreur peut être assez difficile. Et le débogage peut être encore plus difficile.

marque
la source
9

existe-t-il quelque chose qui ne peut être accompli qu'en utilisant plusieurs threads?

Oui. Vous ne pouvez pas exécuter de code sur plusieurs processeurs ou cœurs de processeur avec un seul thread.

Sans plusieurs processeurs / cœurs, les threads peuvent toujours simplifier le code conceptuellement exécuté en parallèle, tel que la gestion des clients sur un serveur - mais vous pouvez faire la même chose sans threads.

Boue
la source
6

Les threads ne sont pas seulement une question de vitesse, mais de concurrence.

Si vous ne proposez pas une application par lots comme suggéré par @Peter, mais plutôt un toolkit à interface graphique tel que WPF, comment interagir avec les utilisateurs et la logique métier avec un seul thread?

En outre, supposons que vous construisiez un serveur Web. Comment serviriez-vous plusieurs utilisateurs simultanément avec un seul thread (sans autre processus)?

Il existe de nombreux scénarios dans lesquels un seul thread simple ne suffit pas. C'est pourquoi les avancées récentes telles que le processeur Intel MIC avec plus de 50 cœurs et des centaines de threads ont lieu.

Oui, la programmation parallèle et concurrente est difficile. Mais nécessaire.

Randolf Rincón Fadul
la source
3
"Un seul thread" peut signifier plusieurs choses - vous pouvez utiliser des suites délimitées pour simuler le multitâche coopératif au sein d'un seul thread (système d'exploitation ou vert), par exemple.
Frank Shearar
Bien sûr, mais je donne un peu de contexte à la question @Frank +1 pour le conseil.
Randolf Rincón Fadul
3
Les threads peuvent rendre les choses plus faciles, mais toutes les tâches que vous avez mentionnées peuvent être effectuées sans thread, et l'ont déjà été. Par exemple, la boucle de l’interface graphique canonique était auparavant while (true) {traite les événements de l’interface graphique; calculer un peu}. Pas de fils nécessaires.
KeithB
Il existe des serveurs Web mono-processus mono-processus. lighttpd par exemple, ou thttpd ou nginx (bien que ce dernier puisse exécuter plusieurs processus, mais le processus par défaut est un. Il s'agit également toujours d'un seul thread). Ils n'ont absolument aucun problème à servir plus d'un utilisateur.
StasM
6

Le multi-threading peut permettre à l'interface graphique de continuer à répondre aux opérations de traitement longues. Sans multi-threading, l'utilisateur resterait bloqué à regarder un formulaire verrouillé pendant l'exécution d'un long processus.

LarsTech
la source
Ce n'est pas tout à fait correct. En théorie, vous pouvez scinder votre longue opération en plusieurs plus petites et mettre à jour le traitement des événements entre les deux.
Sebastian Negraszus
@Sebastion N. Mais si le long processus ne peut être transformé en processus plus petits? La possibilité d'exécuter le processus dans un autre thread peut libérer le thread d'interface graphique (le thread principal) pour qu'il soit toujours réactif.
LarsTech
5

Le code multithread peut bloquer la logique du programme et accéder aux données obsolètes de la même manière que les threads simples.

Les threads peuvent prendre un bogue obscur de quelque chose qu'un programmeur moyen peut s’attendre à déboguer et à le déplacer dans le royaume où des histoires sont racontées sur la chance nécessaire bon moment.

bmike
la source
4

les applications traitant du blocage d'E / S qui doivent également rester sensibles aux autres entrées (l'interface graphique ou d'autres connexions) ne peuvent pas être mises en file indienne

l'ajout de méthodes de vérification dans la bibliothèque d'IO pour voir combien de choses peuvent être lues sans blocage peut aider cela, mais peu de bibliothèques donnent des garanties complètes à ce sujet.

monstre à cliquet
la source
Ils peuvent être simples (et étaient souvent). Le code indique au noyau de démarrer une entrée / sortie et obtient un signal à la fin. En attendant le signal, il peut effectuer un autre traitement.
KeithB
@keith c'est un E / S non bloquant J'ai spécifiquement dit bloquer
cliquet
Mais pourquoi voudriez-vous bloquer les entrées / sorties si vous voulez rester réactif? Existe-t-il des entrées / sorties bloquantes pour lesquelles il n’existe généralement pas d’alternative non bloquante? Je ne peux pas penser à aucun.
KeithB
Le RMI de @keith java bloque et vous pouvez implémenter un rappel (mais cela crée un autre thread), mais cela peut être bloqué par des pare
Reaket Freak
Cela ressemble à une limitation de Java RMI, pas à une limitation inhérente à un code à thread unique. De plus, si vous utilisez RMI, vous avez un "thread" d'exécution séparé, uniquement sur une machine distante.
KeithB
4

Beaucoup de bonnes réponses, mais je ne suis pas sûr que les phrases soient aussi précises que je le voudrais - cela offre peut-être une autre façon de voir les choses:

Les threads ne sont qu'une simplification de la programmation, comme les objets, les acteurs ou les boucles for (Oui, tout ce que vous implémentez avec des boucles que vous pouvez implémenter avec if / goto).

Sans thread, vous implémentez simplement un moteur d'état. J'ai eu à le faire plusieurs fois (la première fois que je l'avais fait, je n'en avais jamais entendu parler - j'ai simplement fait une grosse déclaration de commutateur contrôlée par une variable "State"). Les machines à états sont encore courantes mais peuvent être ennuyeuses. Avec les fils, un énorme morceau du passe-partout s'en va.

Ils facilitent également pour un langage la possibilité de décomposer son exécution à l’aide de plusieurs processeurs conviviaux (de même que les acteurs, je crois).

Java fournit des threads "verts" sur les systèmes où le système d'exploitation ne fournit AUCUN support de threading. Dans ce cas, il est plus facile de voir qu’ils ne sont clairement rien de plus qu’une abstraction de programmation.

Bill K
la source
+1 - Les threads fournissent simplement une abstraction du parallélisme sur des machines essentiellement séquentielles, tout comme les langages de programmation de haut niveau fournissent une abstraction du code machine.
mouviciel
0

Les systèmes d'exploitation utilisent un concept de découpage temporel dans lequel chaque thread obtient son temps d'exécution puis est préempté. Une telle approche peut remplacer le thread tel qu’il est actuellement, mais écrire vos propres planificateurs dans chaque application serait excessif. De plus, vous devrez travailler avec des périphériques d’entrée / sortie, etc. Et aurait besoin d’un soutien du côté matériel, de sorte que vous puissiez déclencher des interruptions pour que votre planificateur soit exécuté. Fondamentalement, vous écririez un nouveau système d'exploitation à chaque fois.

En général, le threading peut améliorer les performances dans les cas où les threads attendent les entrées / sorties ou sont en veille. Il vous permet également de créer des interfaces réactives et d’arrêter des processus tout en effectuant de longues tâches. Et aussi, le threading améliore les choses sur les vrais processeurs multicœurs.

Codeur
la source
0

Tout d'abord, les threads peuvent faire deux choses en même temps (si vous avez plus d'un coeur). Bien que vous puissiez également le faire avec plusieurs processus, certaines tâches ne sont tout simplement pas bien réparties entre plusieurs processus.

En outre, certaines tâches comportent des espaces que vous ne pouvez pas éviter facilement. Par exemple, il est difficile de lire les données d'un fichier sur un disque et de demander à votre processus de faire autre chose en même temps. Si votre tâche nécessite nécessairement beaucoup de lecture de données sur le disque, votre processus passera beaucoup de temps à attendre le disque, peu importe ce que vous ferez.

Deuxièmement, les threads peuvent vous éviter d’optimiser de grandes quantités de code qui ne sont pas critiques en termes de performances. Si vous n'avez qu'un seul thread, chaque élément de code est critique en termes de performances. Si cela bloque, vous êtes submergé - aucune tâche qui serait accomplie par ce processus ne peut progresser. Avec les threads, un bloc n'affectera que ce thread et d'autres threads peuvent venir et travailler sur des tâches qui doivent être effectuées par ce processus.

Un bon exemple est le code de traitement des erreurs rarement exécuté. Supposons qu'une tâche rencontre une erreur très peu fréquente et que le code permettant de gérer cette erreur doive être mis en page en mémoire. Si le disque est occupé et que le processus ne comporte qu'un seul thread, vous ne pouvez pas avancer jusqu'à ce que le code permettant de gérer cette erreur puisse être chargé en mémoire. Cela peut provoquer une réponse en rafale.

Un autre exemple est si vous avez très rarement à faire une recherche de base de données. Si vous attendez que la base de données réponde, votre code prendra un énorme retard. Mais vous ne voulez pas vous donner la peine de rendre tout ce code asynchrone, car il est si rare que vous ayez besoin de faire ces recherches. Avec un fil pour faire ce travail, vous obtenez le meilleur des deux mondes. Un thread pour effectuer ce travail le rend non critique comme il se doit.

David Schwartz
la source