Est-ce que cette règle sur l'usage volatile est stricte?

j'ai vu cette phrase:

la règle générale est, si vous avez variables de type primitif qui doivent être partagé entre plusieurs threads, déclarer ces variables volatile

à partir de cet article , et cette phrase:

En général, toutes les données peuvent être non daté asynchrone devrait être déclaré d'être volatile.

à partir de cette page , considérant maintenant c'est la règle, je voudrais savoir pourrait vous apporter un exemple d'un cas où, malgré l'existence de moteurs asynchrones accès à des données qui ne déclarer que les données volatiles n'a aucune utilisation dans la pratique ou il n'y a pas de tels cas exceptionnel et la règle est stricte.

4
demandé sur John Dibling 2010-11-12 23:20:59

8 réponses

je me souviens quand cet article a été publié et je me souviens des interminables discussions qui ont suivi sur comp.lang.C.++modérer.

autant que je me souvienne, Andrei détourne le volatile mot-clé pour l'utiliser à discriminer entre les différents fonction des surcharges. (Voir cet article de Scott Meyers pour une autre idée.) Ce qu'il n'est brillant, dans ce il permet au compilateur de vous attraper si vous gâchez accès protégé et non protégé aux objets (tout comme le compilateur attrape vous devriez essayer de modifier une constante). Mais outre le fait qu'il vous aide, il n'a rien à voir avec la protection réelle accès concurrent aux objets .

Le problème est que 90% des gens ont une coup d'oeil à l'article et tout ce qu'ils voient est volatile et "threads" dans le même article . Selon leurs connaissances, ils tirent alors soit la conclusion erronée que volatile est bon pour les fils (vous semblez l'avoir fait) ou ils crient à lui pour conduire les autres à tirer les conclusions erronées.

Très peu de gens semblent être en mesure de lire l'article fond et de comprendre ce qu'il fait.

12
répondu sbi 2010-11-12 20:52:32

Je ne peux pas parler pour le réel scénario d'accès asynchrone, puisque je ne suis pas trop bon à la multithreading, mais ce que le volatile modificateur fait est de dire au compilateur:

"Écoutez, ce peut changer à tout moment, afin de ne pas mettre en cache ou le mettre dans un registre ou de faire quelque chose de fou comme ça, d'accord?"

Il ne protège pas contre les écritures asynchrones, il désactive simplement optimisations invalide si la variable peut être changée par des forces externes.

Edit: Comme exemple potentiel, un qui n'implique pas de multithreading (mais, ne nécessite exceptionnellement code alambiqué;), voici un cas où volatile est important:

volatile bool keepRunning = true;
void Stuff() {
    int notAPointer = 0;

    notAPointer = (int)(&keepRunning); //Don't do this! Especially on 64-bit processors!

    while(keepRunning) {
        *(bool*)(notAPointer) = false;
    }

    printf("The loop terminated!");
}

sans ce modificateur volatile, le compilateur pourrait dire " hey, keepRunning n'est jamais modifié, donc je n'ai même pas besoin de générer du code qui le vérifie!", alors qu'en réalité nous ne faisons que la modifier en secret.

(en réalité, cela fonctionnerait probablement encore sur une construction non optimisée. Et, cela pourrait aussi fonctionner si le compilateur est intelligent et remarque le pointeur pris. Mais, le principe est le même)

10
répondu Mike Caron 2010-11-12 20:38:45

Lire ce . Volatile n'a rien à voir avec le multi-threading.

3
répondu BЈовић 2010-11-12 20:28:20

pour donner suite à la réponse de Mike, c'est utile dans des cas comme celui-ci (variables globales utilisées pour éviter la complexité dans cet exemple):

static volatile bool thread_running = true;

static void thread_body() {
    while (thread_running) {
        // ...
    }
}

static void abort_thread() {
    thread_running = false;
}

selon la complexité de thread_body , le compilateur peut choisir de mettre en cache la valeur de thread_running dans un registre lorsque le thread commence à tourner, ce qui signifie qu'il ne remarquera jamais si la valeur change en false. volatile force le compilateur à émettre un code qui vérifiera la variable thread_running réelle sur chaque boucle.

2
répondu cdhowie 2010-11-12 20:29:20

je proposerais une règle beaucoup plus stricte mais très utile: si vous ne comprenez pas exactement ce que volatile fait, ne l'utilisez pas. Utilisez plutôt lock . Si vous ne comprenez pas exactement ce lock et comment l'utiliser, ne pas utiliser le multithreading.

2
répondu jason 2010-11-12 20:35:07

je dirais qu'en théorie ces règles sont absolument correctes, et volatiles est nécessaire chaque fois qu'une variable est accessible par 2 threads. (Même en utilisant des Mutex, car ils n'empêchent pas les optimisations des compilateurs.) Mais dans la pratique les compilateurs sont assez bons pour reconnaître les situations où une variable pourrait être modifiée en dehors d'une fonction particulière de sorte que sa valeur ne devrait pas être mise en cache dans les registres. Dans la plupart des cas, la volatilité n'est pas nécessaire.

j'ai fait une fois tester en MSVC en inspectant la sortie de l'assembleur pour différentes situations, et tout ce qu'il a fallu pour empêcher une variable d'être mise en cache était d'avoir une autre fonction écrivant à la même variable ou prenant son adresse. Les variables globales n'ont jamais été optimisées sauf si "l'optimisation du programme entier" était activée (de sorte que le compilateur peut être sûr que la variable n'est pas modifiée dans d'autres unités de traduction).

2
répondu Timo 2010-11-12 21:42:22

de même, la norme C++ ne spécifie pas comment volatile devrait fonctionner, vous devez regarder ce qu'un compilateur particulier fait pour une plate-forme particulière. Aussi volatile est un peu subtil et ce qu'il fait, dépend du compilateur et du modèle de mémoire de la plateforme cible. Les serrures sont beaucoup plus intuitives à utiliser.

0
répondu Chris O 2010-11-12 20:35:25

avant de prendre l'article que vous avez lié à first too seriously, vous pourriez vouloir lire un autre . Dans un post plus tard sur Usenet , Andrei plus tard admis que les parties de l'article original étaient tout simplement faux, et a indiqué à celui-ci comme donnant une vue plus réaliste des choses (bien que notez que le lien qu'il donne à elle là semble être allé rassis).

0
répondu Jerry Coffin 2010-11-13 00:00:39