La concurrence sans craintes
Le développement sécurisé et efficace dans des contextes de concurrence est un autre objectif majeur de Rust. La programmation concurrente, dans laquelle différentes parties d'un programme s'exécutent de manière indépendante, et le parallélisme, dans lequel différentes parties d'un programme s'exécutent en même temps, sont devenus des pratiques de plus en plus importantes au fur et à mesure que les ordinateurs tirent parti de leurs processeurs multiples. Historiquement, le développement dans ces contextes était difficile et favorisait les erreurs : Rust compte bien changer la donne.
Au début, l'équipe de Rust pensait que garantir la sécurité de la mémoire et éviter les problèmes de concurrence étaient deux challenges distincts qui devaient être résolus de manières différentes. Avec le temps, l'équipe a découvert que les systèmes de possession et de type sont des jeux d'outils puissants qui aident à sécuriser la mémoire et à régler des problèmes de concurrence ! En exploitant la possession et la vérification de type, de nombreuses erreurs de concurrence deviennent des erreurs à la compilation en Rust plutôt que des erreurs à l'exécution. Ainsi, plutôt que d'avoir à passer beaucoup de votre temps à tenter de reproduire les circonstances exactes dans lesquelles un bogue de concurrence s'est produit à l'exécution, le code incorrect va refuser de se compiler et va vous afficher une erreur expliquant le problème. Au final, vous pouvez corriger votre code pendant que vous travaillez dessus plutôt que d'avoir à le faire a posteriori après qu'il ait potentiellement été livré en production. Nous avons surnommé cet aspect de Rust la concurrence sans craintes. La concurrence sans craintes vous permet d'écrire du code dépourvu de bogues subtils et qu'il sera facile de remanier sans risquer d'introduire de nouveaux bogues.
Remarque : pour des raisons de simplicité, nous allons désigner la plupart des problèmes par des problèmes de concurrence plutôt que d'être trop précis en disant des problèmes de concurrence et/ou de parallélisme. Si ce livre traitait spécifiquement de concurrence et/ou de parallélisme, nous serions plus précis. Pour ce chapitre, veuillez garder à l'esprit que nous parlons de concurrence et/ou de parallélisme à chaque fois que nous parlerons de concurrence.
De nombreux langages sont dogmatiques sur les solutions qu'ils offrent pour gérer les problèmes de concurrence. Par exemple, Erlang a une fonctionnalité élégante de passage de messages pour la concurrence mais a une façon étrange de partager un état entre les tâches. Ne proposer qu'un sous-ensemble de solutions possibles est une stratégie acceptable pour les langages de haut niveau, car un langage de haut niveau offre des avantages en sacrifiant certains contrôles afin d'être plus accessible. Cependant, les langages de bas niveau sont censés fournir la solution la plus performante dans n'importe quelle situation donnée et proposer moins d'abstraction vis-à-vis du matériel. C'est pourquoi Rust offre toute une gamme d'outils pour répondre aux problèmes de modélisation quelle que soit la manière qui est adaptée à la situation et aux exigences.
Voici les sujets que nous allons aborder dans ce chapitre :
- Comment créer des tâches pour exécuter plusieurs parties de code en même temps
- Le passage de message en concurrence, qui permet à plusieurs tâches d'accéder à la même donnée
- Les traits
Sync
etSend
, qui étendent les garanties de Rust sur la concurrence tant aux types définis par les utilisateurs qu'à ceux fournis par la bibliothèque standard