2016-10-09 4 views
0

Я пытаюсь написать многопоточную программу и встретить некоторые проблемы.Моя петля не работает должным образом в многопоточном режиме

После я бегу main.c, и я получаю

я: 0
новый поток 0
новый поток 1
я: 1
я: 1

//main.c 
#include <pthread.h> 
#include <stdio.h> 
#include <stdint.h> 
void* routine(void* arg) 
{ 
    int id = (intptr_t) arg; 
    printf("new thread %d\n", id); 
    pthread_exit((void*)(intptr_t) id); 
} 
int main() 
{ 
    pthread_t t[2]; 
    int i; 
    for(i=0; i<2; i++) 
    { 
     int ret = pthread_create (&t[i], NULL, &routine, (void *)(intptr_t) i); 
     if(ret != 0) { 
      printf("Error: pthread_create() failed\n"); 
      return -1; 
     } 
    } 
    int id; 
    /////////here 
    for(i=0; i<2; i++) 
    { 
     printf("i: %d\n",i); 
     pthread_join(t[i], (void **)&id); 
    } 
    /////////here 
    pthread_exit(NULL); 
} 

Мои проблемы:

  • Почему последний цикл работает трижды?
  • Если я изменяю pthread_t t[2] на pthread_t t и создаю дважды, можно ли дважды вызвать pthread_join?

Спасибо за ваше время, читая мой вопрос.

+0

http://ideone.com/MTWpZS –

+2

Для второго вопроса: Нет. Второй вызов 'pthread_create' будет перезаписывать переменную' pthread_t'. –

+0

@JoachimPileborg Я понял! Спасибо @GillBates Моя версия компилятора 'gcc (Ubuntu 4.8.4-2ubuntu1 ~ 14.04.3) 4.8.4', это не работает правильно. Это проблема в каждом случае? –

ответ

2

Сначала добавьте еще немного отладки протоколирования:

int id; 
for(i=0; i<2; i++) 
{ 
    printf("i: %d\n",i); 
    pthread_join(t[i], (void **)&id); 
    printf("id[%d]: %d\n", i, id); 
} 

повторно запустить и запомнить выход.

Затем измените его выглядеть следующим образом

int id; 
for(i=0; i<2; i++) 
{ 
    void * pv; 
    printf("i: %d\n",i); 
    pthread_join(t[i], &pv); /* Add error checking here! */ 
    id = (intptr_t) pv; 
    printf("id: %d\n", id); 
} 

Re перспективе и по сравнению с предыдущей версией.


Как правило:

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

+0

Я все еще думаю, что это немного странно, когда 'i' изменится на 0 после вызова' pthread_join' в моем случае. Я не передал 'i' этой функции. Но в любом случае, спасибо за ваш ответ и предложения. –

+1

@ShawnHuang: 'pthread_join()' ожидает 'void **', адрес указателя, он будет де-ссылаться на него, чтобы стать «void *», а затем присваивает этому «void *» значение указателя, которое вероятно, 8байт. Память, на которую ссылается то, что вы передали, является 'int', она имеет ширину всего 4 байта. Поэтому некоторые другие 4 байта переписываются. Эти 4 байта, скорее всего, принадлежат 'i'. – alk

+0

Я никогда не учитывал этот побочный эффект во время кастинга. В очередной раз благодарим за помощь. –

Смежные вопросы