Pthreads в Mac OS X - проблема мьютексов - PullRequest
2 голосов
/ 11 сентября 2009

Я пытаюсь научиться программировать параллельные алгоритмы на C, используя потоки POSIX. Моя среда - Mac OS X 10.5.5 с gcc 4.

Компиляция:

gcc -Wall -D_REENTRANT -lpthread source.c -o test.o

Итак, моя проблема в том, что если я скомпилирую это в Ubuntu 9.04, он будет работать гладко в порядке потоков, на Mac похоже, что мьютексы не работают, и потоки не ждут получения общей информации. *

Mac:

#1
#0
#2
#5
#3
#4

убунт

#0
#1
#2
#3
#4
#5

Есть идеи?

Следуйте ниже исходного кода:

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

#define NUM_THREADS 6
pthread_mutex_t mutexsum;
pthread_t threads[NUM_THREADS];
long Sum;

void *SumThreads(void *threadid){
    int tmp;
    int i,x[10],y[10];

    // Para cada x e y do vetor, jogamos o valor de i, só para meio didáticos
    for (i=0; i<10 ; i++){
        x[i] = i;
        y[i] = i;
    }


    tmp = Sum;
     for (i=0; i<10 ; i++){
         tmp += (x[i] * y[i]);
     }

       pthread_mutex_lock (&mutexsum);
       Sum += tmp;
       printf("Im thread #%ld sum until now is: %ld\n",threadid,Sum);
       pthread_mutex_unlock (&mutexsum);
       return 0;
}


int main(int argc, char *argv[]){
    int i;
    Sum = 0;

    pthread_mutex_init(&mutexsum, NULL);

    for(i=0; i<NUM_THREADS; i++){
        pthread_create(&threads[i], NULL, SumThreads, (void *)i);
    }

    pthread_exit(NULL);
}

Ответы [ 3 ]

10 голосов
/ 11 сентября 2009

В вашем коде нет ничего, что могло бы заставить ваши потоки работать в ЛЮБОМ порядке. Если в Ubuntu работает по какому-то порядку, это может быть потому, что вам просто повезло. Попробуйте 1000 раз запустить в Ubuntu и посмотрите, будете ли вы получать одни и те же результаты снова и снова.

Дело в том, что вы не можете контролировать то, как планировщик заставит ваши потоки обращаться к процессору (ам). Таким образом, когда вы повторяете цикл for , создающий ваши потоки, вы не можете предполагать, что первый вызов pthread_create будет запущен первым или заблокирует мьютекс. вы создаете первым. Это зависит от планировщика, который находится на уровне ОС, и вы не можете управлять им, если не напишите свое собственное ядро: -).

Если вам нужно последовательное поведение, зачем вам сначала запускать код в отдельных потоках? Если это просто для экспериментов, то я могу подумать об одном решении - использовать pthread_signal, чтобы разбудить определенный поток и запустить его ... Тогда проснувшийся поток может разбудить второй поток и т. Д.

Надеюсь, это поможет.

0 голосов
/ 11 сентября 2009

Я не делаю pthreads на C или любом другом языке (но я делаю многопоточное программирование на высокопроизводительных компьютерах), поэтому этот «ответ» может быть бесполезен для вас;

  • Что в вашем коде требует, чтобы потоки передавали мьютекс в порядке идентификатора потока? Я вижу, что потоки создаются в порядке id, но что требует их выполнения в этом порядке /

  • Если вам требуется, чтобы ваши потоки выполнялись в порядке идентификатора, почему? Кажется, что вы создаете потоки, а затем сериализуете их. Для чего?

  • Когда я программирую в потоках и беспокоюсь о порядке выполнения, я часто пытаюсь создать очень большое количество потоков и посмотреть, что происходит с порядком выполнения.

Как я уже сказал, игнорируйте это, если мое непонимание C и pthreads слишком плохое.

0 голосов
/ 11 сентября 2009

Насколько я помню, переменная, которую вы защищали, фактически не распределяется между процессами. Он существует в своем собственном контексте внутри каждого из потоков. Таким образом, вопрос о том, что будет печататься, зависит только от того, когда каждый поток запланирован.

Я не думаю, что один простой мьютекс позволит вам гарантировать правильность, если правильность определяется как печать 0, 1, 2, 3 ...

то, что делает ваш код, создает несколько контекстов выполнения, используя код в вашей функции sum в качестве кода выполнения. переменная, которую вы защищаете, если она не объявлена ​​как статическая, будет уникальной для каждого вызова этой функции.

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

...