Introduction

Les modules de threading et de multiprocessing en python visent à faire la même chose, c’est-à-dire à faire plusieurs choses en même temps, mais la façon dont le module de threading et le module de multiprocessing s’y prennent est très différente.

C’est pourquoi une définition générale s’impose:

Process: Est une instance d’un programme qui tourne dans un ordinateur (une machine)

Thread: Est une unité de répartition d’une œuvre dans un processus

Un exemple concret: Supposons qu’on est entrain de créer une GUI (interface graphique) et dans cette dernière on aura besoin de cliquer sur un bouton pour afficher un text dans une zone précise de cette interface. De ce fait:

Différences entre Threading et Multiprocessing

Threading:

Multiprocessing:

A noter:

Concurrency: Taches concurrentes

A la première vue on pourra dire que les taches concurrentes (Threading et Couroutines) ne tournent pas en parallère et ceci est vrai en absolue. Car, la définition la plus banale de ce concept dit que que les threads peuvent faire des allers-retours entre les taches quand ils auront le temps. Cependant, en diminuant la fréquence d’altération d’une tache vers une autre on pourra aboutir à un processus qui tendera vers des processus qui tournent en parallèle.

Deux processus peuvent-ils partager le même segment de mémoire partagée?

Oui et non. Généralement, avec les systèmes d’exploitation modernes, lorsqu’un autre processus est dérivé du premier, ils partagent le même espace mémoire avec un jeu de copie en écriture sur toutes les pages. Toutes les mises à jour apportées à l’une des pages de mémoire en lecture-écriture entraînent une copie de la page, il y aura donc deux copies et la page de mémoire ne sera plus partagée entre le processus parent et enfant. Cela signifie que seules les pages en lecture seule ou les pages qui n’ont pas été écrites seront partagées.

Si un processus n’a pas été issu d’un autre (aucun fork), il ne partage généralement pas de mémoire. Une exception est que si vous exécutez deux instances du même programme, elles peuvent partager du code et peut-être même des segments de données statiques, mais aucune autre page ne sera partagée.

Il existe également des appels de mappage de mémoire spécifiques pour partager le même segment de mémoire. L’appel indique si la carte est en lecture seule ou en lecture-écriture. La façon de procéder est très dépendante du système d’exploitation.

Deux threads peuvent-ils partager la même mémoire partagée?

Certainement. En général, toute la mémoire à l’intérieur d’un processus multithread est “partagée” par tous les threads. C’est généralement la définition des threads en ce sens qu’ils s’exécutent tous dans le même espace mémoire.

Les threads ont également la complexité supplémentaire d’avoir des segments de mémoire mis en cache dans la mémoire haute vitesse liés au processeur / noyau. Cette mémoire en cache n’est pas partagée et les mises à jour des pages de mémoire sont vidées dans le stockage central en fonction des opérations de synchronisation. Et c’est là où le GIL (Global Interpreter Lock) de Python intervient.

Assez de théories :D faisons un peu de code !

Multithreading avec/sans Mutex:

Multiprocessing avec Mutex: Notez dans cet exemple le fait qu’on a partagé une liste et des chiffres entre les différents process en utilisant des Mutex.

Multiprocessing avec une Pool: Notez ici le fait que les processus sont indépendant les uns des autres.

Coroutines en utilisant Async/Await:

Coroutines en utilisant ThreadPoolExecutor:

Coroutines en utilisant des Mutex:

Avant de finir: Une question qui se pose toujours: Quand dois-je utiliser le Multithreading ? Quand dois-je utiliser le Multiprocessing ? et Quand dois-je utiliser les Coroutines ?

En gros: