Проблема в связи трех потоков на языке Си (возникает тупик) - PullRequest
0 голосов
/ 30 октября 2019

Я создаю программу, в которой у меня есть 3 связанных списка, и я пытаюсь обновить или удалить узлы из этих связанных списков в этих трех потоках. Но возникает тупик

Вставка и удаление работает нормально. Здесь три переменные var1InUse, var2InUse и var3InUse указывают, используются ли 3 связанных списка или нет (не все три используются во всех потоках). Я помещаю потоки в ожидание на основе var1InUse, var2InUse и var3InUse, как вы можете видеть в коде. Иногда это работает нормально, но иногда возникает тупик. Я искал решение в Интернете, но смог найти его. Правильно ли я использую методы ожидания и подачи сигнала?

    pthread variables declaration

    pthread_mutex_t myMutex = PTHREAD_MUTEX_INITIALIZER;

     pthread_cond_t t1cond = PTHREAD_COND_INITIALIZER;

     pthread_cond_t t2cond = PTHREAD_COND_INITIALIZER;  

     pthread_cond_t t3cond = PTHREAD_COND_INITIALIZER;

    int var1InUse=0,var2InUse=0,var3InUse=0;

THREAD 1

    void* thread1(void* args){
        while(var1InUse || var2InUse ) {
                pthread_cond_wait(&t1cond,&myMutex);}
        var1InUse=1,var2InUse=1;
        while(1){

                pthread_mutex_lock(&myMutex);
                /*
                some other code about adding and removing from                         
                       linkedlist
                */
        var1InUse=0,var2InUse=0;
        pthread_cond_signal(&t2cond);
        pthread_cond_signal(&t3cond);
        pthread_mutex_unlock(&myMutex);}
     }

THREAD 2

    void* thread2(void* args){
        while(var1InUse || var2InUse || var3InUse) {
                pthread_cond_wait(&t2cond,&myMutex);}
        var1InUse=1,var2InUse=1,var3InUse=1;
        while(1){

                pthread_mutex_lock(&myMutex);
                /*
                some other code adding and removing from linkedlist
                */
                var1InUse=0,var2InUse=0,var3InUse=0;
                pthread_cond_signal(&t1cond);
                pthread_cond_signal(&t3cond);
                pthread_mutex_unlock(&myMutex);}
                    }

THREAD 3

     void* thread3(void* args){
        while(var1InUse || var3InUse ) {
                pthread_cond_wait(&t3cond,&myMutex);}
        var1InUse=1,var3InUse=1;
        while(1){

                pthread_mutex_lock(&myMutex);
                /*
                some other code adding and removing from linkedlist
                */
        var1InUse=0,var3InUse=0;
        pthread_cond_signal(&t1cond);
        pthread_cond_signal(&t2cond);
        pthread_mutex_unlock(&myMutex);}
            }

ОСНОВНОЙ МЕТОД

    int main(){
        pthread_t t1,t2,t3,t4;
        pthread_mutex_init(&myMutex,0);
        pthread_create(&t1,NULL,thread1,NULL);
        pthread_create(&t2,NULL,thread2,NULL);
        pthread_create(&t3,NULL,thread3,NULL);
        pthread_join(t1,NULL); 
        pthread_join(t2,NULL);
            pthread_join(t3,NULL);
        pthread_mutex_destroy(&myMutex);
        return 0
            }

Я хочу, чтобы тупик был удален.

1 Ответ

0 голосов
/ 30 октября 2019

Мьютекс, используемый pthread_cond_wait(), должен быть заблокирован перед вызовом функции. Вот выдержка из справочной страницы:

Функции pthread_cond_timedwait() и pthread_cond_wait() должны блокировать переменную условия. Приложение должно гарантировать, что эти функции вызываются с мьютексом, заблокированным вызывающим потоком;в противном случае возникает ошибка (для PTHREAD_MUTEX_ERRORCHECK и устойчивых мьютексов) или неопределенное поведение (для других мьютексов).

Хотя pthread_cond_wait() внутренне разблокирует мьютекс, он снова блокируется до успешного завершения функции:

После успешного возврата мьютекс должен быть заблокирован и принадлежать вызывающему потоку.

Кроме того, вы должны получить доступ к общим переменным var1InUse, var2InUse и var3InUse с заблокированным мьютексом.

Вот модифицированная версия вашего thread1(), которая следует этим правилам. Изменения в других процедурах запуска потока должны быть похожими:

void* thread1(void* args){

    pthread_mutex_lock(&myMutex);

    while(var1InUse || var2InUse ) {
         pthread_cond_wait(&t1cond,&myMutex);
    }
    var1InUse=1,var2InUse=1;

    pthread_mutex_unlock(&myMutex);

    while(1){

        pthread_mutex_lock(&myMutex);
        /*
        some other code about adding and removing from linkedlist
        */
        var1InUse=0,var2InUse=0;
        pthread_cond_signal(&t2cond);
        pthread_cond_signal(&t3cond);
        pthread_mutex_unlock(&myMutex);
    }
    return NULL;
}

(я не совсем уверен, что вышеприведенное верно, потому что из исходного кода не совсем ясно, что такое цикл while(1)должен делать.)

...