Pthreads: ошибка ошибки сегментации - PullRequest
2 голосов
/ 10 марта 2011

У меня есть пара вопросов. Это моя первая настоящая попытка создания многопоточной программы.

ПРИМЕЧАНИЕ - полная программа находится внизу страницы

(для компиляции используйте

g++ -pthread -o <executable file name> <sourcefile>.cpp -fpermissive

)

Я скомпилировал его, используя 64-битную версию Ubuntu Studio 10.10.

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

Кажется, это вызвано строкой, которую я прокомментировал в int main (). Если я прокомментирую эту строку, это не даст мне ошибку ошибки сегментации.

Вот только int main () для удобства:

int main()
{
    pthread_attr_t attr;
    pthread_t threads[30];

    /* Initialize mutex and condition variable objects */
    pthread_mutex_init(&direction_mutex, NULL); 
    pthread_mutex_init(&arrive_mutex,NULL);


    pthread_cond_init (&count_threshold, NULL); 
    pthread_cond_init(&arrive_done, NULL);

    /*
     For portability, explicitly create threads in a joinable state

     I'll take your word for it on that one.
     */
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

   for( int x = 0 ; x < 30 ; x++)
   {
      long random = rand();
      int direction;

       if (random < RAND_MAX/2)
       {
            direction = 0;
       }

       else
       {
            direction = 1;
       }

       directions[x] = direction;
       printf("%d",direction);
    }

    printf("\n");

    currdir = directions[0];

    for(int j = 0 ; j < 30 ; j++)
    {
        if(j != 0)
        {
            pthread_cond_wait(&arrive_done, NULL); // THIS line of code is what is causing the problem
        }



        pthread_create(&threads[j], &attr, OneCar, (void *)&Thread_IDs[j]);
    }

    /* Wait for all threads to complete */
    for (j = 0; j < 30; j++) 
    {
        pthread_join(threads[j], NULL);
    }

    printf("test\n");

    /* Clean up and exit */
    pthread_attr_destroy(&attr);
    pthread_mutex_destroy(&direction_mutex);
    pthread_cond_destroy(&count_threshold);
    pthread_exit (NULL);

}

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

Я пытался использовать эту блокировку мьютекса, чтобы не позволять int main () запускать новый поток до тех пор, пока не завершится последний поток, поскольку предполагается, что в этой программе потоки выполняются в порядке FIFO.

Без этого кода поведение меняется.

Большую часть времени он начинается с потока 0, затем переходит к потоку 3,4, иногда даже 5, прежде чем вернуться к потоку 1.

Иногда он начинается в потоке 3, затем переходит в поток 4, затем поток 0 ... Я не могу понять, почему он это делает.

Это каждый раз другая последовательность выполнения потоков, но она никогда не бывает 0,1,2,3,4, как должно быть

Вот вывод с закомментированной строкой:

*** Output of program with "pthread_cond_wait(&arrive_done, NULL);" commented out:


101110010101011111010001000010
ArriveBridge(): Car 1 goes accross the bridge
ExitBridge(): car 1 has left the bridge
Arrivebridge(): Thead 0 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 0 goes accross the bridge
ExitBridge(): car 0 has left the bridge
Arrivebridge(): Thead 5 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 5 goes accross the bridge
ExitBridge(): car 5 has left the bridge
Arrivebridge(): Thead 3 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 3 goes accross the bridge
ExitBridge(): car 3 has left the bridge
ArriveBridge(): Car 2 goes accross the bridge
ExitBridge(): car 2 has left the bridge
ArriveBridge(): Car 4 goes accross the bridge
ExitBridge(): car 4 has left the bridge
Arrivebridge(): Thead 6 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 6 goes accross the bridge
ExitBridge(): car 6 has left the bridge
Arrivebridge(): Thead 7 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 7 goes accross the bridge
ExitBridge(): car 7 has left the bridge
Arrivebridge(): Thead 8 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 8 goes accross the bridge
ExitBridge(): car 8 has left the bridge
Arrivebridge(): Thead 9 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 9 goes accross the bridge
ExitBridge(): car 9 has left the bridge
Arrivebridge(): Thead 10 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 10 goes accross the bridge
ExitBridge(): car 10 has left the bridge
Arrivebridge(): Thead 11 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 11 goes accross the bridge
ExitBridge(): car 11 has left the bridge
ArriveBridge(): Car 13 goes accross the bridge
ExitBridge(): car 13 has left the bridge
Arrivebridge(): Thead 12 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 12 goes accross the bridge
ExitBridge(): car 12 has left the bridge
Arrivebridge(): Thead 14 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 14 goes accross the bridge
ExitBridge(): car 14 has left the bridge
ArriveBridge(): Car 15 goes accross the bridge
ExitBridge(): car 15 has left the bridge
ArriveBridge(): Car 16 goes accross the bridge
ExitBridge(): car 16 has left the bridge
Arrivebridge(): Thead 18 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 18 goes accross the bridge
ExitBridge(): car 18 has left the bridge
Arrivebridge(): Thead 17 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 17 goes accross the bridge
ExitBridge(): car 17 has left the bridge
ArriveBridge(): Car 19 goes accross the bridge
ExitBridge(): car 19 has left the bridge
Arrivebridge(): Thead 21 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 21 goes accross the bridge
ExitBridge(): car 21 has left the bridge
ArriveBridge(): Car 20 goes accross the bridge
ExitBridge(): car 20 has left the bridge
ArriveBridge(): Car 22 goes accross the bridge
ExitBridge(): car 22 has left the bridge
Arrivebridge(): Thead 23 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 23 goes accross the bridge
ExitBridge(): car 23 has left the bridge
Arrivebridge(): Thead 24 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 24 goes accross the bridge
ExitBridge(): car 24 has left the bridge
ArriveBridge(): Car 25 goes accross the bridge
ExitBridge(): car 25 has left the bridge
ArriveBridge(): Car 26 goes accross the bridge
ExitBridge(): car 26 has left the bridge
ArriveBridge(): Car 27 goes accross the bridge
ExitBridge(): car 27 has left the bridge
ArriveBridge(): Car 29 goes accross the bridge
ExitBridge(): car 29 has left the bridge
Arrivebridge(): Thead 28 is trying to go in the opposite direction, it must wait for traffic to clear
ArriveBridge(): Car 28 goes accross the bridge
ExitBridge(): car 28 has left the bridge
test

Это вывод БЕЗ этой закомментированной строки

****output of program before commenting pthread_cond_wait(&arrive_done, NULL); out:


101110010101011111010001000010
Segmentation fault

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

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

Спасибо за ваше время

Ответы [ 3 ]

7 голосов
/ 10 марта 2011

Вам нужно передать мьютекс на pthread_cond_wait, вы передаете NULL.

Для случайных данных (по крайней мере, в Linux), считанных с /dev/random или /dev/urandom. Вы также можете попробовать: direction = (rand() >> 8) & 1

4 голосов
/ 10 марта 2011

Ваш основной цикл должен быть:

pthread_mutex_lock(&arrive_mutex);
for(int j = 0 ; j < 30 ; j++)
{
    if(j != 0)
    {
        // Pass a locked mutex as the second parameter.
        pthread_cond_wait(&arrive_done, &arrive_mutex);
        // This releases the lock and suspends the thread.
        // When the condition variable is signaled. It re-establishes the lock
        // then releases the thread. If another processes is holding the lock
        // the released thread is stalled until it can acquire the lock.
        //
        // This means the child thread should acquire the lock on the mutex.
        // call signal and then release the lock. If the child does not
        // aquire the lock first then there is the potential for the child to
        // reach the signal before the parent waits() if this happens then the
        // parent will suspend forever (as nobody else will signal).

    }

    pthread_create(&threads[j], &attr, OneCar, (void *)&Thread_IDs[j]);
}
// Unlock the mutex afterwords.
pthread_mutex_unlock(&arrive_mutex);
2 голосов
/ 10 марта 2011

Я думаю, вам нужно передать мьютекс вместо NULL в pthread_cond_wait.Страница man сообщает:

int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);

Эти функции атомарно освобождают mutex и заставляют вызывающий поток блокировать условиепеременная cond ;«атомно» здесь означает «атомарно в отношении доступа другого потока к мьютексу, а затем к условной переменной».

Он пытается освободить нулевой мьютекс с таким кодом, каким он является.

...