2017-07-12 3 views
1
std::uint64_t foo() 
{ 
    static std::uint64_t var = 0u; 

    std::lock_guard<std::mutex> lock(mutex); 

    std::uint64_t b; 

    do 
    { 
     b = bar(); 
    } 
    while (b <= var); 

    var = b; 

    return b; 
} 

Supposons que nous ayons deux threads. Laissez le premier thread lu variable var dans un registre avant d'appeler lock() et le deuxième thread lire la variable var dans un registre avant d'appeler lock(). Ensuite, le premier thread change var mais le deuxième thread ne voit pas la modification car il conserve la valeur dans le registre. Est-ce que cette situation vraiment mauvaise peut arriver? En général, seules les variables locales sont optimisées de cette façon: elles sont placées dans des registres et lues par la suite plutôt qu'à partir de la mémoire principale. Et les variables globales ne devraient pas être optimisées de cette manière que je comprends. Mais qu'en est-il des variables locales statiques?Une variable locale statique peut-elle être faussement optimisée?

+0

"* ... Cette situation peut-elle vraiment se produire? .. *" - Oui. Les effets de synchronisation d'un 'std :: mutex' est que' unlock() '* synchronise avec *' lock() '. Mais vous parlez d'utiliser l'objet avant 'lock()' La seule garantie qu'un mutex fournit est celle, modifications de 'bar' par thread ** A ** dans la séquence' lock() '-'unlock()', sera visible à un autre thread, ** B ** après ** B ** 'lock()' s le mutex. – WhiZTiM

+0

Vous devez verrouiller la ressource AVANT de l'utiliser, sinon l'autre thread pourrait la verrouiller entre l'assignation et le verrou, ce qui conduit à une condition de concurrence – Dynamitos

+0

@WhiZTiM * C++ 11 * ne garantit-il pas une sécurité thread-safe? –

Répondre

0

La variable locale statique a une durée de vie de la variable globale, elle a simplement une portée de fonction. Vous devez le protéger comme vous le feriez avec une variable globale appropriée (mutex/atomic).

Note: Si vous utilisez tout type de variable dans plusieurs threads (je veux dire quand les fils utilisent la variable même), alors vous devez le rendre thread-safe. Même, si c'est une variable globale. Même, si la variable est stockée en mémoire. Stocker une variable en mémoire ne la rend pas sûre. La sécurité des threads n'est pas une préoccupation car certaines variables peuvent figurer dans les registres. Il pourrait y avoir une CPU, où différents cœurs ne synchronisent pas automatiquement leurs caches. Ainsi, pour une variable, il peut y avoir plusieurs valeurs dans le cache de chaque core.