Quest-ce quun verrou de mémoire ?

Historiquement, tous les programmes informatiques étaient écrits de manière totalement séquentielle. C'est simple à lire, à écrire et à comprendre. Il est également simple à exécuter pour un ordinateur et nécessite un matériel relativement simple. Avec ce paradigme de conception, les deux seules façons d'augmenter les performances du système sont d'écrire un code plus efficace et d'augmenter la vitesse du processeur. Augmenter l'efficacité du code peut être possible, mais il s'agit généralement d'un processus complexe avec des résultats souvent limités.

Pendant des décennies, les performances ont pu être réduites en attendant de nouveaux processeurs plus efficaces. Comme décrit par la loi de Moore, les performances des processeurs doublent environ tous les deux à trois ans. Malheureusement, la plupart de ces gains de performances provenaient de l'utilisation de nœuds de fabrication de plus en plus petits. La technologie moderne a du mal à réduire la taille des nœuds au rythme historique, grâce à des difficultés matérielles à travailler à l'échelle du nanomètre.

Pour contourner ce problème, les architectes de processeurs modernes ont choisi d'ajouter plusieurs cœurs de processeur aux processeurs. Chaque cœur de processeur peut agir indépendamment sur une tâche différente. S'ils ne peuvent pas combiner le même problème, ils peuvent travailler sur deux problèmes simultanément. Ce changement architectural fondamental offre de nombreuses performances supplémentaires, mais il ne profite pas directement aux processus individuels, bien qu'il réduise les conflits de temps processeur.

Pour tirer parti des processeurs multicœurs, le code doit être écrit de manière multithread. Chaque thread peut ensuite être exécuté simultanément, en adaptant les performances en fonction du nombre de threads et de cœurs de processeur disponibles. Faire cela, cependant, se heurte à un nouveau défi, la «condition de concurrence».

Remarque : Certaines tâches ne peuvent pas être multithread, tandis que d'autres peuvent être massivement multithread. Les gains de performance possibles dépendent du travail effectué.

Conditions de course

Les logiciels multithread peuvent tirer parti de plusieurs cœurs. Des dangers rôdent dans ces eaux, prêts à piéger le programmeur inexpérimenté. Une condition de concurrence peut se produire lorsque deux threads différents interagissent avec le même bit de mémoire.

Un exemple simple pourrait être deux threads essayant de vérifier et d'incrémenter une variable simultanément. Disons que a=0 . Deux threads différents exécutent alors leurs fonctions et, à un moment donné, vérifient a et l'incrémentent de un. Généralement, vous vous attendez à ce que le résultat de deux threads ajoutant un à zéro soit deux. La plupart du temps, cela devrait être le cas. Vous pouvez obtenir un résultat différent si les deux threads utilisent cette fonctionnalité spécifique au bon moment.

Dans ce cas, le premier thread lit la valeur de a . Avant que le premier thread ne puisse incrémenter la valeur de a , le deuxième thread le lit. Maintenant, le premier thread ajoute un à zéro, mais le deuxième thread croit déjà que la valeur est zéro, ajoutant un à zéro. Le résultat est que la valeur finale de a est 1 et non 2.

Course au pire scénario

Bien que l'exemple ci-dessus puisse ne pas sembler particulièrement mauvais, il peut avoir des effets dramatiques. Et si la valeur de a sélectionne le mode de fonctionnement d'une machine ? Que se passe-t-il si des modes de fonctionnement spécifiques de cette machine peuvent être dangereux, voire mortels ?

Les conditions de course n'ont pas non plus besoin d'être aussi simples. Par exemple, il peut être possible qu'un thread lise une section de mémoire en même temps qu'un autre thread y écrit. Dans ce cas, le fil de lecture peut obtenir un mélange étrange des données d'avant et d'après. Disons que la vérification est une simple vérification vrai/faux.

Si la variable disait vrai au début de la lecture mais était en train d'être remplacée par le mot faux, le résultat de l'opération de lecture pourrait être quelque chose comme « trlse ». Ce n'est pas "vrai" ou "faux". Ne pas être l'une des deux options dans un choix binaire entraînerait presque certainement le plantage de l'application. Cette corruption de la mémoire peut entraîner de nombreux problèmes de sécurité, tels que le déni de service et l'élévation des privilèges.

Verrouiller la course

Savoir quels bits de mémoire dans un programme sont partagés entre différents threads est essentiel pour éviter une condition de concurrence. Rien ne doit être fait si une variable n'est jamais contrôlée et accessible que par un seul thread. Si deux threads ou plus peuvent accéder à une variable, vous devez vous assurer que toutes les opérations sur cet élément de mémoire sont terminées indépendamment les unes des autres.

Cette indépendance est obtenue grâce à une serrure. Dans le code d'un programme, il faut mettre un verrou lors de l'écriture d'une fonction qui opère sur une mémoire partagée. Ce verrou empêche les autres threads d'accéder à cette partie de la mémoire jusqu'à ce que le verrou soit relâché.

La serrure n'est pas la plus élégante des solutions. D'une part, il a des frais généraux de mémoire. Il peut également forcer un thread à se bloquer, en attendant qu'un verrou soit libéré. Selon la situation, le verrou peut ne pas être libéré pendant très longtemps ou ne pas être libéré du tout. Dans le pire des cas, le déverrouillage d'un verrou pourrait dépendre de quelque chose qui se passe dans un autre thread bloqué, conduisant à un blocage.

Il est essentiel d'optimiser l'utilisation des serrures. Vous pouvez contrôler la granularité du verrou. Par exemple, si vous modifiez des données dans un tableau, vous pouvez verrouiller le tableau entier ou verrouiller uniquement la ligne modifiée. Verrouiller toute la table serait un verrou de granularité grossière. Cela minimise la surcharge liée à l'implémentation d'un trop grand nombre de verrous, mais augmente le risque qu'un autre thread soit bloqué par le verrou. Verrouiller uniquement la ligne serait un verrou de granularité fine. Cela est beaucoup moins susceptible d'interférer avec d'autres threads, mais cela signifie que des verrous déchirés seront nécessaires, ce qui augmentera la surcharge totale.

Conclusion

Un verrou de mémoire est un outil de code utilisé pour garantir l'atomicité des opérations en mémoire dans un environnement multithread. En verrouillant une partie de la mémoire avant de l'utiliser, vous pouvez être sûr qu'aucun comportement inattendu ne peut se produire en raison d'une condition de concurrence. Les verrous de mémoire entraînent une surcharge de mémoire, mais peuvent également provoquer un blocage.

Le blocage est l'endroit où un autre thread tente d'opérer sur une mémoire verrouillée. Le fil reste là, bloqué jusqu'à ce que le verrou soit libéré. Cela peut causer des problèmes si la libération du verrou nécessite qu'un autre thread fasse quelque chose, car il peut être bloqué avant qu'il ne puisse terminer la condition préalable pour libérer le verrou le bloquant. Les verrous de mémoire peuvent être évités en écrivant des codes non bloquants. Cependant, cela peut être complexe et moins performant que d'utiliser des verrous. N'oubliez pas de laisser vos commentaires ci-dessous.



Leave a Comment

Fix Always on Display ne fonctionne pas sur Galaxy Watch

Fix Always on Display ne fonctionne pas sur Galaxy Watch

Pour résoudre les problèmes de Always on Display sur Samsung Galaxy Watch, désactivez le mode d

La mémoire du Chromebook peut-elle être mise à niveau ?

La mémoire du Chromebook peut-elle être mise à niveau ?

Découvrez si la mémoire du Chromebook peut être mise à niveau et comment optimiser ses performances avec la gestion de la RAM.

Comment numériser sur Canon MX492

Comment numériser sur Canon MX492

Apprenez à numériser à partir de limprimante et du scanner multifonctions Canon MX492.

Principes de base de limpression 3D : astuces pour lisser les impressions PLA

Principes de base de limpression 3D : astuces pour lisser les impressions PLA

Vous avez du mal à lisser les impressions PLA ? Ce guide convivial pour les débutants vous montrera comment vous pouvez le faire facilement avec des méthodes efficaces.

Correction dune erreur Chromebook lors de la configuration de limprimante

Correction dune erreur Chromebook lors de la configuration de limprimante

Si votre Chromebook indique qu

Quest-ce que le TDP ?

Quest-ce que le TDP ?

Découvrez ce qu

Comment réinitialiser la clé Amazon Fire TV aux paramètres dusine

Comment réinitialiser la clé Amazon Fire TV aux paramètres dusine

Découvrez comment effectuer une <strong>réinitialisation d

Comment utiliser Spotify dans le nouveau Garmin Venu

Comment utiliser Spotify dans le nouveau Garmin Venu

Découvrez comment connecter votre montre Garmin Venu à Spotify et profitez de vos playlists préférées tout en restant actif !

Comment utiliser Samsung Flow

Comment utiliser Samsung Flow

Découvrez comment utiliser Samsung Flow pour connecter votre smartphone Samsung à votre PC et bénéficier de fonctionnalités avancées telles que le partage de fichiers et la synchronisation des notifications.

Comment faire une capture décran sur un ordinateur portable Chromebook

Comment faire une capture décran sur un ordinateur portable Chromebook

Découvrez comment faire une capture d