조건 변수 프로그램은 2 개의 스레드에서 작동하지만 3 개의 스레드에서는 작동하지 않습니다.

희망없는 방랑자

그래서 나는 변수를 0에서 100까지 증가시키는 2 개의 스레드가있는이 프로그램을 가지고 있으며 잘 작동합니다.

#include<stdio.h>
#include<stdlib.h>
#include<semaphore.h>
#include<pthread.h>

int contor;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args) {
    int id = (int)args;
    while(1) {
        pthread_mutex_lock(&mutex);
        if (contor >= 100) {
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }

        while (contor %2 == id) {
        pthread_cond_wait(&cond,&mutex);
        }

        contor++;
        printf("Thread %d increment: %d\n",id,contor);


        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
}

int main(void) {
    pthread_t th1, th2,th3;

    if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
        perror("Error!\n");
        exit(1);
    }
    if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
        perror("Error!\n");
        exit(2);
    }


    pthread_join(th1, NULL);
    pthread_join(th2, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

결과는 다음과 같습니다.

Thread 1 increment: 1
Thread 0 increment: 2
Thread 1 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 0 incre.. and so on ,which is nice.

그러나 문제는 내가 3 개의 스레드로 시도 할 때 더 이상 작동하지 않는 것입니다. 3 번만 변경했는데 문제가 무엇인지 모르겠습니다.

#include<stdio.h>
#include<stdlib.h>
#include<semaphore.h>
#include<pthread.h>

int contor;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args) {
    int id = (int)args;
    while(1) {
        pthread_mutex_lock(&mutex);
        if (contor >= 100) {
            pthread_cond_signal(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }

        while (contor %3 == id) {
        pthread_cond_wait(&cond,&mutex);
        }

        contor++;
        printf("Thread %d increment: %d\n",id,contor);


        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&mutex);
    }
}

int main(void) {
    pthread_t th1, th2,th3;

    if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
        perror("Error!\n");
        exit(1);
    }
    if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
        perror("Error!\n");
        exit(2);
    }
    if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
        perror("Error!\n");
        exit(3);
    }



    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
        pthread_join(th3, NULL);


    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

똑같은 일을해야합니까? 지금은 3 개만. 왜 작동하지 않습니까? 이것이 작동하는 방법입니다

Thread 2 increment: 1
Thread 2 increment: 2
Thread 1 increment: 3
Thread 1 increment: 4
Thread 2 increment: 5
Thread 1 increment: 6
WhozCraig

당신이 스레드주기를 보장하려는 경우입니다 N (스레드 수) 모듈로 카운터까지 스레드 대기를 할 필요가 특정의 그것은 아무것도 아니다까지, ID는 하지만, 특정 ID를 표시합니다. ID가 두 개인 경우 하나가 아니면 다른 ID 여야합니다. 그러나 3 개로 2 개의 브레이킹 케이스와 1 개의 대기 케이스가 있습니다. 스케줄러는 해제하려는 두 개의 예비 스레드 중 어느 것이 든 자유롭게 선택할 수 있습니다.

그러나 이것을 변경하면 :

while (contor %3 == id)

이에:

while (contor %3 != id)

당신은 주어진 스레드가됩니다 시행됩니다 모듈의 ID입니다 값을 기록.

그러나 이것만으로는 충분하지 않습니다 . 또한 모든 웨이터 를 깨워 야 합니다 . 이전에는 두 개의 스레드 만있을 때 항상 동일한 웨이터가있었습니다. 활성 스레드가 아닌 "다른 사람"이었습니다. 이 a pthread_cond_signal는 특정 대상 스레드 (실행되지 않는 유일한 스레드)로 지정되며 당연히 다음 스레드이기도합니다.

스레드가 3 개 이상인 경우 잠재적으로 깨어 난 단일 스레드 pthread_cond_signal가 contor modulo N id를 가진 스레드 가 아닐 가능성이 있습니다. 실제로 스레드가 많을수록 이런 일이 발생할 가능성이 높아집니다. 이 경우 스레드는 대기 상태로 돌아가지만 대기중인 다른 사람은 다시 시작되지 않습니다. 당신은 이것을 우연에 맡기고 싶지 않습니다. 다음 웨이터가 신호를받을 수 있도록 모든 웨이터가 깨어 있는지 확인하십시오 .

마십시오 하지 또 다른 전송하여이 문제를 해결 pthread_cond_signal어딘가에. 대신 브로드 캐스트를 보내십시오. 다음을 변경하십시오.

pthread_cond_signal(&cond);

이에:

pthread_cond_broadcast(&cond);

이렇게하면 활성 대기중인 모든 스레드가 결국에는 균열이 생기고 모듈로 N contor과 일치 하는 스레드 contor가 범프, 인쇄, 다음 브로드 캐스트를 보내고 다시 대기 상태로 돌아갈 수 있습니다.

따라서 코드에 대한 최소한의 변경은 다음과 같습니다.

#include<stdio.h>
#include<stdlib.h>
#include<stdint.h>      // added for intptr_t
#include<inttypes.h>    // added for printf formatter for intptr_t
#include<pthread.h>

int contor;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args) {
    intptr_t id = (intptr_t)args; // proper way to pass an integer via thread param
    while(1) {
        pthread_mutex_lock(&mutex);
        if (contor >= 100) {
            pthread_cond_broadcast(&cond);
            pthread_mutex_unlock(&mutex);
            pthread_exit(NULL);
        }

        while (contor %3 != id) {
        pthread_cond_wait(&cond,&mutex);
        }

        contor++;
        printf("Thread %"PRIdPTR " increment: %d\n",id,contor);


        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&mutex);
    }
    return NULL; // should always have well-defined return value
}

int main(void) {
    pthread_t th1, th2,th3;

    if(pthread_create(&th1, NULL, &incrementare, (void *)0) < 0) {
        perror("Error!\n");
        exit(1);
    }
    if(pthread_create(&th2, NULL, &incrementare, (void *)1) < 0) {
        perror("Error!\n");
        exit(2);
    }
    if(pthread_create(&th3, NULL, &incrementare, (void *)2) < 0) {
        perror("Error!\n");
        exit(3);
    }

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);
    pthread_join(th3, NULL);

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

결과는 다음과 같습니다.

Thread 0 increment: 1
Thread 1 increment: 2
Thread 2 increment: 3
Thread 0 increment: 4
Thread 1 increment: 5
Thread 2 increment: 6
Thread 0 increment: 7
Thread 1 increment: 8
Thread 2 increment: 9
Thread 0 increment: 10
....
Thread 0 increment: 97
Thread 1 increment: 98
Thread 2 increment: 99
Thread 0 increment: 100
Thread 1 increment: 101
Thread 2 increment: 102

라이브보기

추가 2 개의 출력은 천장 중단 조건을 확인하는 코드 가 cvar-predicate 루프 이전에 있기 때문 입니다. 그것은해야 ,하지만 난 주소로 당신을 위해 떠난다.

그러나 이렇게하면 궁극적으로 작업에서 여러 스레드를 느슨하게 만드는 목적이 무효화됩니다. 이상적으로 는 실제로 작업을 수행하는 데 사용할 수 있는 스레드 를 원합니다 . 작업이 단일 전역에만 영향을 미친다는 것은 스레딩의 실제 목적을 다소 떨어 뜨립니다 (분명히 스레딩을 사용하여 100까지 세지 않을 것입니다. 루프의 단일 스레드가 이상적입니다).


그럼에도 불구하고 프로그램의 압축 버전이 아래에 표시됩니다. N_THREADS의 값을 변경하여 N_COUNT출력의 차이를 확인합니다.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>
#include <pthread.h>

#define N_THREADS 7
#define N_COUNT   100

int contor;  // 0

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

void *incrementare(void *args)
{
    intptr_t id = (intptr_t)args;
    pthread_mutex_lock(&mutex);
    while(1)
    {
        while (contor < N_COUNT && contor % N_THREADS != id)
            pthread_cond_wait(&cond, &mutex);

        if (contor == N_COUNT)
            break;

        printf("Thread %"PRIdPTR" increment: %d\n", id, ++contor);
        pthread_cond_broadcast(&cond);
    }
    pthread_mutex_unlock(&mutex);
    return NULL;
}

int main(void)
{
    pthread_t ar[N_THREADS];
    intptr_t id = 0;

    for (int i=0; i<N_THREADS; ++i)
    {
        if(pthread_create(ar+i, NULL, &incrementare, (void *)id++) < 0) {
            perror("Error!\n");
            exit(1);
        }
    }

    for (int i=0; i<N_THREADS; ++i)
        pthread_join(ar[i], NULL);

    return 0;
}

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관