2012-09-17 4 views
3

Disons que j'ai le code suivant:mémoire de C Commande Cohérence

void* p0 = nullptr; 
void* p1 = alloc_some_data(); 
void f1() { 
    p0 = p1; 
    p1 = nullptr; 
} 

On suppose que f1 est exécuté sur un fil 1. Est-il possible que (en laissant le code tel qu'il est) un autre thread peut à un certain point, voir p0 et p1 comme nullptr (si le compilateur ou le matériel réorganise les instructions telles que la deuxième assignation avant la première)?

La raison pour laquelle je pose cette question est parce que je veux implémenter un garbage collector et je veux savoir si j'ai besoin d'accéder aux pointeurs du thread GC utilisant des instructions atomiques (std::atomic). Il n'y a pas de problème si le thread GC voit p0 == p1 == alloc_some_data() mais il y aura des problèmes si le thread GC voit p0 == p1 == nullptr car il signalera alors les données précédemment dans p1 comme inaccessibles quand il est clairement accessible.

Répondre

0

Oui. Bien que ce ne soit pas nécessairement probable, c'est tout à fait possible parce que ces opérations ne sont pas atomiques.

un (de quelques scénarios possibles) est la suivante:

Thread 2: Get value of p0 (null) 

Thread 1: Get value of p1 (non-null) 
      p0 = p1 
      p1 = nullptr 

Thread 2: Get value of p1 (null) 

Vous devez utiliser une certaine forme de contrôle d'accès (c.-à- un mutex).

+0

D'après ce que je comprends, l'avantage de tracer gc sur le comptage de ref évite les verrous (par incréments de refs). Si chaque mise à jour de référence dans un thread mutateur nécessite un verrou mutex, alors où est le gain de performance par rapport au comptage de ref? L'approche de traçage gc blote alors le chemin du code avec des verrous comme les méthodes de comptage de ref (dans les threads de mutateur), n'est-ce pas? Est-il possible d'écrire un gc de traçage où les threads mutateurs peuvent mettre à jour une référence avec une simple instruction MOV? Quelqu'un peut-il me diriger vers une direction (un article ou un livre ...)? –

+0

Je ne connais pas assez la garbage collection pour commenter. Personnellement, j'aime le comptage de références parce que la mémoire est libérée le plus tôt possible. Certains systèmes d'exploitation fournissent des instructions d'incrémentation et de décrémentation atomiques beaucoup plus rapides que l'utilisation de mutex. Dans de tels cas, le comptage de référence gagne. Si vous utilisez Windows/Visual Studio, vous pouvez jeter un oeil à la sémantique 'volatile' spécifique à Microsoft. – paddy

+1

@DaniloCarvalho: Je ne connais pas très bien le GC, mais de nombreux GC qui ne sont pas référencés sont * stop-the-world * GC: l'environnement arrêtera tous les threads, effectuera GC (relocalisation des objets et mise à jour des pointeurs) tous les threads continuent. –

2

Si vous lisez un objet dans un thread écrit par un autre thread sans synchronisation, vous avez une course de données. Cela implique clairement que votre garbage collector aura besoin de lire les valeurs en utilisant une sorte de synchronisation. En ce qui concerne votre question initiale: il n'y a rien dans votre code indiquant que l'écriture à p0 devient visible avant l'écriture de p1, c'est-à-dire, un autre thread peut, en effet, voir les deux être nulles. Ceci est indépendant des primitives de synchronisation utilisées pour communiquer avec un autre thread: il n'y a pas d'ordre entre ces deux écritures.

0

La réponse à votre question est oui, mais dépend du compilateur et du processeur. Je pense que vous devez également faire p0 et p1 volatile. Pour arrêter le réordonnancement, vous pouvez utiliser les instrinsics _mm_sfence et _mm_lfence (pour x86/x64)

+1

Rendre les objets 'volatils' est totalement hors de propos en ce qui concerne le C++ 2011. C++ 2011 a aussi des fonctions standardisées pour introduire des clôtures (cependant, je ne peux pas les utiliser car je n'ai pas essayé de les utiliser). –

+0

@ DietmarKühl Avez-vous un lien pour soutenir le manque de besoin de volatiles? Comment le compilateur sait-il ne pas mettre en cache une lecture? – James

+0

Pour autant que je sache, «volatile» est requis lorsque le matériel/les interruptions peuvent altérer la mémoire. Ce n'est pas le cas ici. Microsoft a ajouté sa propre sémantique à 'volatile ', ce qui est peut-être ce à quoi vous pensez, mais ce n'est pas conforme à la norme ISO. – paddy