2016-04-17 1 views
5

En supposant que x est une variable inter-thread partagée et func renvoie toujours 0, le code ci-dessous contient-il une course de données en termes de C11 et C++ 11? Veuillez supposer que x est écrit dans deux threads différents, toujours avec un verrou approprié, sauf l'instruction switch ci-dessous.L'accès non protégé à une variable partagée est-il toujours une course de données?

int x; // global variable 

... 

int y; // local variable 

... 

switch (func()) 
{ 
    case 1: 
    { 
    x = 0; 
    y = 1; 
    break; 
    } 
    case 2: 
    { 
    x = 0; 
    y = 2; 
    break; 
    } 
    case 3: 
    default: 
    { 
    y = 3; 
    break; 
    } 
} 

Il y a une note dans la norme (les deux C11 et 11 C++) qui empêche les transformations du compilateur qui introduit une course de données au code. Est-ce que le compilateur est autorisé à transformer le code comme ci-dessous? Le code ci-dessous contient certainement une course de données mais la question est de savoir si le compilateur l'a introduit ou s'il était déjà dans le code original. Il y avait un accès non protégé à une variable partagée, mais inaccessible.

int x; // global variable 

... 

int y; // local variable 

... 

temp = x; 
x = 0; 
switch (func()) 
{ 
    case 1: 
    { 
    y = 1; 
    break; 
    } 
    case 2: 
    { 
    y = 2; 
    break; 
    } 
    case 3: 
    default: 
    { 
    x = temp; 
    y = 3; 
    break; 
    } 
} 
+0

Sans mécanismes de synchronisation attendent des courses de données, oui, vous devriez plutôt avoir un 'std :: atomique x,' –

+0

Oui, absolument –

+0

Il est pas seulement.. une course de données C n'a pas de concept de processus concurrents – Olaf

Répondre

4

Dans la norme C++, une course est définie:

1,10/4: conflit entre les deux évaluations d'expression, si l'un d'eux modifie un emplacement de mémoire et l'autre accès ou modifie la même emplacement de mémoire.

1,10/21: L'exécution d'un programme contient une course de données si elle contient deux actions contradictoires dans différents fils, au moins un des qui est non atomique, et ne se produit avant que l'autre. Une telle course de données entraîne un comportement indéfini.

Supposant que vous avez plusieurs threads en cours d'exécution le même code, en raison du fait que func() serait toujours retourner 0 (votre réclamation), aucun des fils pourrait changer le contenu de x. De plus, y est une variable locale d'une fonction exécutée par un thread, elle n'est donc pas partagée. Par conséquent, aucune condition de concurrence ne peut se produire dans ce scénario.

Le compilateur ne peut pas faire les transformations correspondant au second extrait parce que:

1,10/22: transformations du compilateur qui introduisent les affectations à un emplacement de mémoire potentiellement partagée qui ne serait pas modifiée par la la machine abstraite est généralement exclue par cette norme, car une telle affectation peut écraser une autre assignation par un autre thread dans les cas où une exécution de machine abstraite n'aurait pas rencontré de course de données .

Mais si vous écrivez l'extrait, dans les conditions expliquées ci-dessus pourraient rencontrer des conditions de course depuis le x est pas atomique, et il pourrait y avoir accès en lecture dans un thread (temp=x) et en écriture dans l'autre (soit x=0 . ou dans la section par défaut de l'autre fil (x=temp)

+0

Merci pour la réponse, c'est ce que je m'attendais, mais j'ai des doutes sur un point. Je ne comprends pas comment le fait que * func * renvoie toujours 0 influence la relation * arrive-avant * entre les affectations à x dans l'instruction switch et les autres accès à x dans différents threads. – mrn

+1

@mrn Il n'y a pas de happpens-before entre les threads autres que ceux fournis par la synchronisation. – Yakk

+0

Les relations "Happens-before" sont un outil d'analyse de la propagation de séquençage issue de la synchronisation de threads lors de l'exécution. Si aucun des threads n'utilise la variable partagée, il n'y a pas d'autre effet d'ordre au-delà du fait que la valeur initiale est arrivée avant le reste. En passant, je ne vois pas synchro dans votre code, et x n'est pas atomique. donc si funct retournerait autre chose que 0, des courses pourraient se produire parce qu'il n'y a rien qui permette un ordre d'accès à cette variable. – Christophe