2010-09-24 4 views
1

Я создаю n потоков &, затем начиная с выполнения после барьера.Барьеры для синхронизации потоков

В глобальном пространстве данных:

int bkdown = 0; 

В главном():

pthread_barrier_init(&bar,NULL,n); 

for(i=0;i<n;i++) 
{ 
pthread_create(&threadIdArray[i],NULL,runner,NULL); 
if(i==n-2)printf("breakdown imminent!\n"); 
if(i==n-1)printf("breakdown already occurred!\n"); 
} 

В нити функция бегун:

void *runner(void *param) 
{ 
pthread_barrier_wait(&bar); 

if(bkdown==0){bkdown=1;printf("barrier broken down!\n");} 

     ... 

pthread_exit(NULL); 
} 

Ожидаемый заказ:

breakdown imminent! 
barrier broken down! 
breakdown already occurred! 

Фактический порядок:(проверены неоднократно)

breakdown imminent! 
breakdown already occurred! 
barrier broken down!! 

Может кто-нибудь объяснить, почему я не получаю "broken down" сообщений перед "already occurred" сообщением?

ответ

2
for(i=0;i<n;i++) 
{ 
pthread_create(&threadIdArray[i],NULL,runner,NULL); 
if(i==n-2)printf("breakdown imminent!\n"); 
if(i==n-1)printf("breakdown already occurred!\n"); 
} 

Ничто не останавливает этот цикл от момента выполнения до i == n-1. pthread_create() просто запускает поток, который нужно запустить. Он не ждет, чтобы он начинался или заканчивался. Таким образом, вы находитесь во власти планировщика, который может решить продолжить выполнение вашего цикла или переключиться на один из вновь созданных потоков (или сделать оба в системе SMP).

Вы также активируете барьер до n, поэтому ни в коем случае ни одна из нитей не пройдет мимо барьера, пока вы не сотворите все из них.

3

Порядок выполнения потоков зависит от операционной системы. Просто потому, что вы запускаете поток, это не означает, что ОС будет запускать его немедленно.

Если вы действительно хотите, чтобы контролировать порядок, в котором выполняются потоки, вы должны поставить какое-то синхронизацию там (с мьютексами или переменных условием.)

1

В дополнение к ответам н.у.к., и Старки вы должны принять во внимание, что у вас есть еще один сериализации в вашем коде, который часто пренебрегают: вы делаете IO на одной и той же FILE переменной, а именно stdin.

Доступ к этой переменной является внутренним мьютексом и порядок, в котором ваши потоки n+1 (включая вызывающий поток) получают доступ к этому мьютексу, определяется реализацией, воспринимайте его в основном как случайный в вашем случае.

Итак, порядок, в котором вы получаете свой вывод printf, - это порядок, в котором ваши потоки проходят через эти червоточины.

0

Вы можете получить ожидаемый заказ в один из двух способов

  • Создать каждый поток с более высоким приоритетом, чем в основном потоке. Это гарантирует, что новый поток будет запускаться сразу после создания и ждать на барьере.
  • Переместите «пробой неизбежной! \ N» перед pthread_create() и вызовите вызов sched_yield() после каждого pthread_create().Это позволит запланировать созданный поток для выполнения.