2017-07-20 1 views
0

Je ne suis pas certain de la sémantique de la mémoire du processus d'initialisation C++. Disons que nous avons le programme suivant.Sémantique mémoire d'initialisation dans un environnement multithread (C++)

#include <iostream> 
#include <thread> 

using namespace std; 

void func(int* arr, int s) 
{ 
    for (int i = 0; i < s; ++i) 
    { 
     cout << arr[i] << endl; 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    int *a = new int[10]; 
    for (int i = 0; i < 10; ++i) 
    { 
     a[i] = i; 
    } 

    // Do I need some sort of memory barrier here? 
    std::thread t(func, a, 10); 
    t.join(); 
    return 0; 
} 

Le nouveau thread verra-t-il un tableau initialisé correctement? Ou ai-je besoin de l'insertion d'une sorte de barrière de mémoire entre les deux. Comment le langage C++ définit-il la sémantique de la mémoire pour l'initialisation?

Ma préoccupation est que toutes les écritures de tableau un [10] peut s'asseoir dans un tampon d'écriture de cpu, et nous commençons un nouveau fil sur un cpu différent, qui ne peut observer l'initialisation écrit. Avons-nous besoin d'une barrière de mémoire pour l'initialisation afin de pouvoir être observée par un thread plus récent qui s'exécute sur un cpus différent?

Répondre

1

Il existe une relation "arrive avant" entre les opérations dans le parent avant l'exécution du constructeur de thread et la procédure de thread s'exécutant dans l'enfant. En particulier, la norme dit (f étant la procédure de fil):

synchronisation: L'achèvement de l'appel du constructeur est synchronisé avec le début de l'invocation de la copie de f.

Il se trouve dans la section [thread.thread.constr]

+0

Merci pour la citation. J'ai eu du mal à lire la norme. J'ai trouvé tes citations. Par "synchronise avec", je suppose que cela signifie que le compilateur pourrait insérer une clôture juste avant l'invocation de la copie de f pour s'assurer que tous les magasins avant l'invocation de f seront observés? –

+0

@OliverYoung: La norme ne dit rien sur les clôtures de mémoire, car toutes les architectures CPU n'en ont pas besoin. La norme dit où le compilateur doit s'assurer que les effets secondaires sont visibles, et où les opérations se chevauchent (créant une condition de concurrence), et le compilateur est responsable de l'utilisation de toute fonctionnalité de CPU qui donne le comportement spécifié. –

+0

Je vois. Juste pour être très clair, la partie d'initialisation synchronise les invocations/"arrive-avant" de la copie de f. Cela signifie qu'il n'y a pas de condition de concurrence et que vous n'avez pas besoin d'opérations de synchronisation, n'est-ce pas? –