그래서 나는 변수를 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
당신이 스레드주기를 보장하려는 경우입니다 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] 삭제
몇 마디 만하겠습니다