Что произойдет, если передать адрес переменной стека в функцию pthread? - PullRequest
0 голосов
/ 12 декабря 2018

Я пишу программу, чтобы потоки выполнялись по порядку. Но когда я передаю адрес переменной стека в функцию потока, а программа просто ждет всегда. Вот программа:

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

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t order_cond = PTHREAD_COND_INITIALIZER;
int count = 0;

void* thread_print(void* num){
    sleep(10);
    int number = *(int*)num;
    //printf("%d", number);
    for(int i = 0; i < 10; i++){
        pthread_mutex_lock(&mutex);
        while((count%3)!=number){
            pthread_cond_wait(&order_cond, &mutex);
        }
        switch(number){
            case 0:{
                printf("A");
                break;
            }
            case 1:{
                printf("B");
                break;
            }
            case 2:{
                printf("C");
                break;
            }
        }
        count++;
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&order_cond);
    }
    return (void*)0;
}

int main(){
    pthread_t p_id[3];
    printf("fail\n");
    void* tret;
    for(int i = 0; i<3;i++){
        int success = pthread_create(&p_id[i], NULL, thread_print, (void*)&i);
        if(success != 0){
            printf("fail\n");
        }
    }
    for(int i = 0; i < 3; i++){
        pthread_join(p_id[i], &tret);
    }
    //sleep(10);
    pthread_mutex_lock(&mutex);
    while(count < 30){
        pthread_cond_wait(&order_cond, &mutex);
    }
    pthread_mutex_unlock(&mutex);
    return 0;
}

Я делаю некоторыеКогда я передаю i функции потока и use int number = (int)num, она может работать очень хорошо.Так что же происходит, когда я просто передаю адрес i в функцию потока?

1 Ответ

0 голосов
/ 12 декабря 2018

Но когда я передаю адрес переменной стека в функцию потока, и программа просто ждет всегда.

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

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

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

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

Например:

    // Note that 'i' itself is converted to void *
    int success = pthread_create(&p_id[i], NULL, thread_print, (void *) i);
    // ...

void *thread_print(void *num) {
    // Note that 'num' is converted directly (back) to an int, not dereferenced
    int number = (int) num;
    // ...

Обратите внимание, что sleep() нерешить проблемы синхронизации.Лучше всего, это скрывает их, но в вашем конкретном случае это подчеркивает их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...