2017-08-26 1 views
3
var condition bool 
var wg sync.WaitGroup 
for _, item := range items { 
    wg.Add(1) 
    go func(item) { 
     if meetsCondition(item) { 
      condition = true 
     } 
     wg.Done() 
    }(item) 
} 
wg.Wait() 
// is it safe to check condition here? 

Il ya une discussion de cette question à l'ancien forum aller ici: https://groups.google.com/forum/#!topic/golang-nuts/5oHzhzXCcmM La réponse était oui, il est sûr. Ensuite, la discussion digress à utiliser de l'atome, etc., ce qui n'est pas ce que je veux demander.Est-ce que WaitGroup.Wait() implique une barrière de mémoire dans ce cas?

Il n'y a même pas une mention de WaitGroup dans la spécification et sa documentation dit WaitGroup.Wait: "Attendez blocs jusqu'à ce que le compteur WaitGroup est zéro." qui ne pas définir une relation qui se passe avant (ou le fait?). Cela signifie-t-il que la première réponse "Il est sûr de vérifier l'état après wg.Wait Returns" n'est pas officielle? Si c'est officiel, quelles en sont les raisons? Merci beaucoup si vous répondez.

Mise à jour: Cette mise à jour est effectuée après les réponses de @ peterSO @ ravi. Merci. Bien, évidemment, il peut y avoir une condition de concurrence si vous choisissez le nombre d'éléments> 1. Conseil: la condition peut être définie uniquement sur vrai. Pourtant, j'ai la même question.

Et probablement, je aurais dû déclaré que:

  1. architectures sous-jacentes ne peuvent être que x86, x64 ou ARM
  2. nombre d'articles peuvent être 1

Mise à jour 2 I question de suivi créée pour le cas où le nombre d'articles == 1 ici: Can you make this 'incorrectly synchronized' test fail?

Répondre

0

Eh bien, il est absolument sûr de vérifier condition après wg.Wait(), mais vous devez protéger condition avec un mutex pour éviter qu'il ne soit "écrit à" simultanément par plusieurs routines go. C'est pourquoi @peterSO est en train de frapper une condition de course b'cos à la ligne 20 dans son code qui est condition = true en train d'essayer de mettre condition en même temps. Voici un exemple https://play.golang.org/p/o3v6s_2qsY avec 20k go rountines.

Comme une meilleure pratique que je recommande, on ajoute defer wg.Done() au début de la fonction de routine go, de sorte que même s'il y a des déclarations de retour entre, wg.Done() est toujours appelé.

1

Oui. Il existe une relation entre wg.Wait() et wg.Done(). Ce simple fait est pour une raison non mentionnée dans doc ou aller MM #7948. Merci Ian Lance Taylor pour l'avoir clarifié golang-nuts/5oHzhzXCcmM. A propos de la condition de course, vous pouvez lire plus dans le même fil. Un peu décevant que dans un langage qui se dit concurrent, il faut compter sur un «bon mot» pour faire les choses de base (à droite).