Maison > développement back-end > C++ > Comment implémenter un compteur ABA dans C 11 à l'aide de la comparaison et de l'échange atomiques ?

Comment implémenter un compteur ABA dans C 11 à l'aide de la comparaison et de l'échange atomiques ?

Linda Hamilton
Libérer: 2025-01-03 03:51:39
original
718 Les gens l'ont consulté

How to Implement an ABA Counter in C  11 Using Atomic Compare-and-Swap?

Implémentation du compteur ABA avec C 11 CAS

Le problème ABA se produit lorsque la valeur d'un emplacement mémoire est modifiée deux fois, avec une modification intermédiaire qui définit il retrouve sa valeur d'origine. Cela peut faire croire à un thread s'appuyant sur des opérations de comparaison et d'échange atomiques (CAS) qu'une valeur n'a pas changé, alors qu'en fait elle a changé.

Pour éviter le problème ABA, une solution courante consiste à créer un compteur qui s'incrémente à chaque changement d'emplacement mémoire. Ce compteur est incrémenté atomiquement avec le changement, afin que l'opération CAS puisse vérifier si le compteur a également changé depuis la dernière opération.

En C 11, la fonction std::atomic_compare_exchange_weak fournit une opération CAS atomique. Cependant, il ne permet pas la modification simultanée de plusieurs variables, comme la valeur et le compteur.

Pour implémenter un compteur ABA avec C 11 CAS, nous devons stocker le compteur et la valeur dans la mémoire adjacente emplacements, de sorte qu’une seule opération CAS puisse mettre à jour les deux valeurs de manière atomique. Ceci peut être réalisé en utilisant une structure avec deux membres, où le premier membre est la valeur et le deuxième membre est le compteur :

struct Node {
  std::atomic<int> value;
  std::atomic<int> counter;
};
Copier après la connexion

Avec cette structure de données, nous pouvons utiliser la fonction std::atomic_compare_exchange_weak pour implémentez le compteur ABA :

void modifyValue(Node& node, int newValue) {
  int expectedValue = node.value.load(std::memory_order_relaxed);
  int expectedCounter = node.counter.load(std::memory_order_relaxed);
  bool success;
  do {
    success = node.value.compare_exchange_weak(expectedValue, newValue, std::memory_order_acq_rel);
    success = node.counter.compare_exchange_weak(expectedCounter, expectedCounter + 1, std::memory_order_acq_rel);
  } while (!success);
}
Copier après la connexion

Dans cet exemple, la fonction modifierValue charge d'abord la valeur attendue et le compteur à l'aide du std::memory_order_relaxed ordre mémoire, qui permet de lire les valeurs dans le désordre et peut conduire à un déchirement.

La fonction std::atomic_compare_exchange_weak est ensuite utilisée pour comparer la valeur attendue et le compteur avec les valeurs actuelles dans l'emplacement mémoire. Si les valeurs correspondent, la nouvelle valeur et le compteur sont écrits à l'emplacement en utilisant l'ordre mémoire std::memory_order_acq_rel, ce qui garantit que l'écriture est visible par les autres threads une fois l'opération terminée.

Si les valeurs ne correspondent pas match, la fonction compare_exchange_weak échoue et la boucle est à nouveau exécutée, chargeant la dernière valeur attendue et le dernier compteur avant de tenter à nouveau l'échange atomique.

Cette implémentation garantit que le compteur est incrémenté atomiquement avec la valeur, évitant ainsi le problème ABA et garantissant que les threads peuvent s'appuyer en toute sécurité sur la cohérence de la valeur.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal