Pthread аргументы - PullRequest
       7

Pthread аргументы

3 голосов
/ 25 марта 2012

У меня проблемы с передачей аргументов в новые потоки, у меня есть следующие

 doRowOffset[0] = 0;
 for(threads = 1; threads < NUMTHREADS; threads++){
      doRowOffset[threads] = threads;
      printf("Do row: %d\n", doRowOffset[threads]);
      pthread_create(&threadHandler[threads], NULL, multiplyRows, (void *) &doRowOffset[threads]);
 }

и

void * multiplyRows(void * dealWithRows){
        int offset = *((int *) dealWithRows);
        printf("%d\n", *((int *) dealWithRows));
        printf("Offset: %d\n", offset);
        printf("Size: %d\n", partitionSize/NUMTHREADS);
        printf("Calculated Offset: %d\n", offset*partitionSize/NUMTHREADS);
        ...

Теперь я ожидаю увидеть следующий вывод

Сделать строку: 1
1
Смещение: 1
Размер: 2
Расчетное смещение: 2

Однако я продолжаю получать значения мусора или 0 для dealWithRows, когда попадаю в потокя делаю что-то не так с передачей аргументов?

Ответы [ 2 ]

2 голосов
/ 25 марта 2012

Если вы передадите адрес переменной, которая меняется, вы должны ожидать, что она может измениться на вас: -)

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

Затем, когда первый поток окончательно разыменует адрес, вы изменили базовое значение.

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

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

Что-то вроде:

pthread_create (&threadHandler[threads], NULL, multiplyRows,
    (void *) doRowOffset); // <<-- Note, removed the '&'.

в основном потоке и:

int offset = (int) dealWithRows;

в дочерней ветке.

2 голосов
/ 25 марта 2012

Если doRowOffset является int, вы не должны видеть мусор , если только поток, создающий функцию , не завершится и вы не выделите переменную в стеке, и она будет перезаписана.

Но учтите, что существует только одна переменная, и вы передаете ее адрес, поэтому при запуске потока он может увидеть обновленное значение.

Передать фактическое значение:

pthread_create(&threadHandler[threads], NULL, multiplyRows, (void *) threads);

void * multiplyRows(void * dealWithRows){
    int offset = (int) dealWithRows);
}
...