28 votes

Pourquoi les fils pourraient-ils être considérés comme "mauvais" ?

Je lisais le FAQ SQLite et je suis tombé sur ce passage :

Les fils sont mauvais. Évitez-les.

Je ne comprends pas bien l'affirmation "Le pain est mauvais". Si c'est vrai, alors quelle est l'alternative ?

Ma compréhension superficielle des fils est la suivante :

  • Les fils de discussion permettent la concurrence. Sinon, la puissance du processeur sera gaspillée à attendre des E/S lentes (par exemple).
  • Mais l'inconvénient est que vous devez synchroniser votre logique pour éviter la contention et que vous devez protéger les ressources partagées.

Note : Comme je ne connais pas les fils de discussion sur Windows, j'espère que la discussion se limitera aux fils de discussion sur Linux/Unix.

17voto

Pavel Minaev Points 60647

Lorsque les gens disent que "les threads sont mauvais", ils le font généralement dans le contexte de dire que "les processus sont bons". Les threads partagent implicitement tout l'état de l'application et les handles (et les threads locaux sont opt-in). Cela signifie qu'il y a de nombreuses occasions d'oublier de se synchroniser (ou de ne pas comprendre que vous devez vous synchroniser !) tout en accédant à ces données partagées.

Les processus disposent d'un espace mémoire distinct, et toute communication entre eux est explicite. De plus, les primitives utilisées pour la communication interprocessus sont souvent telles que vous n'avez pas besoin de synchronisation du tout (par exemple, les pipes). Et vous pouvez toujours partager l'état directement si vous en avez besoin, en utilisant la mémoire partagée, mais cela est également explicite dans chaque instance donnée. Il y a donc moins d'occasions de faire des erreurs, et l'intention du code est plus explicite.

13voto

Sean Woods Points 1071

Réponse simple comme je l'entends...

La plupart des modèles de threading utilisent la "concurrence d'état partagée", ce qui signifie que deux processus d'exécution peuvent partager la même mémoire au même moment. Si un thread ne sait pas ce que fait l'autre, il peut modifier les données d'une manière que l'autre thread n'attend pas. Cela provoque des bogues.

Les fils sont "diaboliques" parce que vous devez vous faire à l'idée n des threads travaillant tous sur la même mémoire au même moment, et toutes les choses amusantes qui vont avec (blocages, conditions de course, etc.).

Vous pouvez vous renseigner sur les modèles de concurrence de Clojure (structures de données immuables) et d'Erlang (transmission de messages) pour trouver des idées alternatives sur la façon d'atteindre des objectifs similaires.

13voto

Jeremy Friesner Points 16684

Ce qui rend les threads "diaboliques", c'est que dès que vous introduisez plus d'un flux d'exécution dans votre programme, vous ne pouvez plus compter sur un comportement déterministe de votre programme.

C'est-à-dire : Pour un même ensemble d'entrées, un programme monofilaire fera (dans la plupart des cas) toujours la même chose.

Un programme multithread, avec le même ensemble d'entrées, peut très bien faire quelque chose de différent à chaque fois qu'il est exécuté, à moins qu'il ne soit très soigneusement contrôlé. En effet, l'ordre dans lequel les différents threads exécutent les différents morceaux de code est déterminé par le planificateur de threads du système d'exploitation combiné à une horloge système, ce qui introduit une bonne dose d'"aléatoire" dans ce que fait le programme lorsqu'il s'exécute.

Le résultat est le suivant : le débogage d'un programme multithread peut être beaucoup plus difficile que celui d'un programme monothread, car si vous ne savez pas ce que vous faites, il peut être très facile de se retrouver avec une condition de course ou un bug de blocage qui n'apparaît (apparemment) qu'au hasard une ou deux fois par mois. Le programme semblera parfait pour votre service d'assurance qualité (puisqu'il n'a pas un mois pour l'exécuter), mais une fois qu'il sera sur le terrain, les clients vous diront que le programme a planté et que personne ne peut reproduire le plantage.... bleah.

Pour résumer, les threads ne sont pas vraiment "maléfiques", mais ils sont un grigri puissant et ne devraient pas être utilisés à moins que (a) vous en ayez vraiment besoin et (b) vous savez dans quoi vous vous engagez. Si vous les utilisez, faites-le avec parcimonie et essayez de rendre leur comportement aussi stupide et simple que possible. En particulier avec le multithreading, si quelque chose peut mal tourner, cela arrivera (tôt ou tard).

8voto

cletus Points 276888

Je l'interpréterais d'une autre manière. Ce n'est pas que fils sont mauvais, c'est que effets secondaires sont diaboliques dans un contexte multithread (ce qui est beaucoup moins accrocheur à dire).

Un effet secondaire dans ce contexte est quelque chose qui affecte l'état partagé par plus d'un thread, qu'il soit global ou simplement partagé. J'ai récemment écrit un revue de Spring Batch et l'un des extraits de code utilisé est :

private static Map<Long, JobExecution> executionsById = TransactionAwareProxyFactory.createTransactionalMap();
private static long currentId = 0;

public void saveJobExecution(JobExecution jobExecution) {
  Assert.isTrue(jobExecution.getId() == null);
  Long newId = currentId++;
  jobExecution.setId(newId);
  jobExecution.incrementVersion();
  executionsById.put(newId, copy(jobExecution));
}

Maintenant, il y a au moins trois des problèmes sérieux de threading en moins de 10 lignes de code ici. Un exemple d'effet secondaire dans ce contexte serait la mise à jour de la variable statique currentId.

La programmation fonctionnelle (Haskell, Scheme, Ocaml, Lisp, etc.) tend à privilégier les fonctions "pures". Une fonction pure est une fonction sans effets secondaires. De nombreux langages impératifs (par exemple Java, C#) encouragent également l'utilisation d'objets immuables (un objet immuable est un objet dont l'état ne peut pas changer une fois créé).

La raison (ou du moins l'effet) de ces deux choses est largement la même : elles rendent le code multithreading beaucoup plus facile. Une fonction pure est par définition threadsafe. Un objet immuable est, par définition, threadsafe.

L'avantage des processus est qu'il y a moins d'état partagé (en général). Dans la programmation C UNIX traditionnelle, l'exécution d'un fork() pour créer un nouveau processus entraînerait le partage de l'état du processus, ce qui était utilisé comme moyen de communication interprocessus (IPC), mais cet état est généralement remplacé (avec exec()) par autre chose.

Mais les fils sont beaucoup Ils sont moins chers à créer et à détruire et nécessitent moins de ressources système (en fait, le système d'exploitation lui-même peut ne pas avoir de notion de threads, mais vous pouvez quand même créer des programmes multithreads). Ces programmes sont appelés fils verts .

6voto

jalf Points 142628

L'article dont vous avez donné le lien semble s'expliquer très bien. L'avez-vous lu ?

Gardez à l'esprit qu'un thread peut faire référence à la construction du langage de programmation (comme dans la plupart des langages procéduraux ou OOP, vous créez un thread manuellement et vous lui demandez d'exécuter une fonction), ou ils peuvent faire référence à la construction matérielle (chaque cœur de processeur exécute un thread à la fois).

Le thread au niveau matériel est évidemment inévitable, c'est la façon dont le CPU fonctionne. Mais le CPU ne se soucie pas de la façon dont la concurrence est exprimée dans votre code source. Il n'est pas nécessaire que ce soit par un appel de fonction "beginthread", par exemple. Il suffit d'indiquer au système d'exploitation et à l'unité centrale quels fils d'instruction doivent être exécutés.

Ce qu'il veut dire, c'est que si nous utilisions de meilleurs langages que C ou Java avec un modèle de programmation conçu pour la concurrence, nous pourrions obtenir la concurrence gratuitement. Si nous avions utilisé un langage de passage de messages ou un langage fonctionnel sans effets secondaires, le compilateur aurait été capable de paralléliser notre code pour nous. Et cela aurait fonctionné.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X