4

Here is piece (very simplified, with global var's and other "smells") of C code, which uses posix barrier primitive to sincronize thread start.

#include <pthread.h>
#include <stdio.h>

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;
}

I can't understand, why "Entering thread ..." string occurs not simultaneously in the output? When i run above programm, usually get alike output:

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 

What i expect, is simultaneously starting of two threads, and appearing of "Entering thread ..." strings in sequence in the output. Compile it with: gcc barrier.c -pthread

What i'm doing wrong with that?

ars
  • 707
  • 4
  • 14

2 Answers2

3

What your barrier is doing is preventing Thread 1 from producing any output before Thread 2 is created.

After both threads are created, both cross the barrier and are unblocked. After that you are not asserting any control as to how they are interleaved. So, thread 1 happens to get its time slice and produces all its output; then thread 2 gets its time slice and produces all its output.

Try moving the barrier after the "Enter" output to get a better understanding.

BaseZen
  • 8,650
  • 3
  • 35
  • 47
2

All the barrier does is ensure that neither thread can return from the barrier wait call before the other thread has entered it. There is no ordering relationship between the subsequent output except that each individual stdio call is atomic. The fact that you're seeing all the output for one thread before all the output for the other is simply a consequence of scheduling and/or which thread succeeds in getting the internal mutex in stdout first on each try (once it's gotten it on one and the other thread goes to sleep waiting for the mutex, the first thread has an advantage re-acquiring this mutex first again).

If you want to see output interleaved, add another call to pthread_barrier_wait on your barrier immediately before or after each call to printf.

You would also be statistically much more likely to see interleaving by mere chance if you increased the number of output lines from 5 to 10000 or so.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711