Comprendre le mécanisme de barrière posix

Voici un morceau (très simplifié, de variables globales et autres “odeurs”) de code C, qui utilise la primitive barrière posix pour créer un thread thread.

#include  #include  pthread_barrier_t barrier; void* thread_func(void* aArgs) { pthread_barrier_wait(&barrier); printf("Entering thread %p\n", (void*)pthread_self()); int i; for(i = 0 ; i < 5; i++) printf("val is %d in thread %p \n", i, (void*)pthread_self()); } int main() { pthread_t thread_1, thread_2; pthread_barrier_init(&barrier, NULL, 2); pthread_create(&thread_1, NULL, (void*)thread_func, NULL); printf("Thread %p created\n", (void*)thread_1); usleep(500); pthread_create(&thread_2, NULL, (void*)thread_func, NULL); printf("Thread %p created\n", (void*)thread_2); pthread_join(thread_1, NULL); pthread_join(thread_2, NULL); pthread_barrier_destroy(&barrier); return 0; } 

Je ne comprends pas pourquoi la chaîne “Entering thread …” ne se produit pas simultanément dans la sortie? Lorsque je cours au-dessus de programme, obtenez généralement la même sortie

 Thread 0xb74fdb40 created Thread 0xb6cfcb40 created Entering thread 0xb6cfcb40 val is 0 in thread 0xb6cfcb40 val is 1 in thread 0xb6cfcb40 val is 2 in thread 0xb6cfcb40 val is 3 in thread 0xb6cfcb40 val is 4 in thread 0xb6cfcb40 Entering thread 0xb74fdb40 val is 0 in thread 0xb74fdb40 val is 1 in thread 0xb74fdb40 val is 2 in thread 0xb74fdb40 val is 3 in thread 0xb74fdb40 val is 4 in thread 0xb74fdb40 

Ce que j’attends, c’est le démarrage simultané de deux threads et l’apparition de chaînes “Saisie de threads …” dans l’ordre de la sortie. Comstackz-le avec: gcc barrier.c -pthread

Qu’est-ce que je fais mal avec ça?

Votre barrière empêche le thread 1 de produire une sortie avant que le thread 2 ne soit créé.

Une fois les deux threads créés, les deux traversent la barrière et sont débloqués. Après cela, vous n’exercez aucun contrôle sur leur entrelacement. Ainsi, le fil 1 arrive à prendre sa tranche de temps et produit toute sa sortie; alors le thread 2 obtient sa tranche de temps et produit toute sa sortie.

Essayez de déplacer la barrière après la sortie “Entrée” pour mieux comprendre.

Tout ce que la barrière fait est de s’assurer qu’aucun des threads ne peut revenir de l’appel attendre avant que l’autre thread ne l’ait entrée. Il n’y a pas de relation d’ordre entre la sortie suivante, sauf que chaque appel stdio individuel est atomique. Le fait de voir toutes les sorties d’un thread avant toutes les sorties de l’autre est simplement une conséquence de la planification et / ou du fil qui réussit à obtenir le mutex interne dans la sortie stdout premier à chaque essai et l’autre thread s’endort en attendant le mutex, le premier thread a l’avantage de ré-acquérir ce mutex).

Si vous souhaitez voir les sorties entrelacées, ajoutez un autre appel à pthread_barrier_wait sur votre barrière immédiatement avant ou après chaque appel de printf .

Vous auriez également beaucoup plus de chances de voir l’entrelacement par hasard si vous augmentiez le nombre de lignes de sortie de 5 à 10 000 environ.