내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
스레드(Thread): 프로세스의 엔터티이자 CPU 스케줄링 및 디스패치의 기본 단위입니다. 스레드 자체는 기본적으로 시스템 리소스를 소유하지 않으며 실행에 필수적인 몇 가지 리소스(예: 프로그램 카운터, 레지스터 집합, 스택)만 소유하지만 프로세스가 소유한 모든 리소스를 다른 스레드와 공유할 수 있습니다. 이는 동일한 프로세스에 속합니다. 스레드는 다른 스레드를 만들고 삭제할 수 있습니다. 동일한 프로세스의 여러 스레드가 동시에 실행될 수 있습니다. 스레드는 작업 중에 간헐적으로 동작합니다. (위 내용은 "컴퓨터 레벨 4 튜토리얼 - 운영 체제 원리"에서 발췌한 것입니다.)
스레드에 관해서는 프로세스의 정의에 대해 이야기할 필요가 있습니다. 프로세스는 특정 독립적인 기능을 가진 프로그램입니다. 프로세스는 시스템에서 자원 할당 및 스케줄링을 위한 독립적인 단위입니다. (위 내용은 "컴퓨터 레벨 4 튜토리얼 - 운영 체제 원리"에서 발췌한 것입니다.)
프로세스의 정의는 다소 복잡합니다. 프로세스가 프로그램, 데이터 및 프로세스 제어 블록으로 구성되어 있는 것을 살펴보겠습니다. 그 중 프로그램은 프로세스 정의에서 "어떤 독립적인 기능을 가진 프로그램"에 해당합니다. 그러나 프로세스에는 프로그램 자체 외에도 데이터(리소스로 이해될 수 있음)와 프로세스 제어 블록도 필요합니다. 데이터 및 프로세스 제어 블록은 프로그램이 실행될 때 필수적인 리소스입니다. 프로그램은 이러한 리소스를 사용하여 "프로세스"라고 부르는 해당 활동을 수행합니다.
프로세스의 두 가지 기본 속성:
프로세스는 리소스를 소유할 수 있는 독립적인 단위입니다.
프로세스는 독립적으로 예약되고 발송될 수 있는 기본 단위입니다.
스레드가 처음 확립되었을 때는 프로세스의 위 두 가지 속성을 분리하기 위한 것이었습니다. 스레드는 "CPU 스케줄링 및 디스패치의 기본 단위"를 구성합니다. 동시에 프로세스의 병렬 실행을 실현할 수 있으며, 동일한 프로세스의 스레드는 프로세스의 모든 리소스를 공유할 수 있으며, 이는 동일한 프로세스의 다른 스레드가 프로세스 리소스에 액세스하는 것을 만족시킬 수 있습니다. 스레드의 출현은 프로세스의 두 가지 속성을 교묘하게 분리하여 프로세스가 병렬 실행 요구 사항을 더 잘 처리할 수 있게 해줍니다.
스레드는 실행 중인 함수입니다. POSIX 스레드는 구현 집합이 아니라 표준 집합입니다. openmp 스레드와 같은 다른 표준이 있습니다.
스레드 식별자: pthread_t (구체적인 내용은 모르겠습니다. 회사마다 다르게 구현하며, Linux에서는 int입니다.)
px axm 명령은 프로세스와 스레드(프로세스 아래의 스레드를 나타냄)를 확인합니다. px ax -L을 사용하면 경량 스레드를 볼 수 있습니다.
int pthread_equal(pthread_t t1, pthread_t t2); 두 스레드의 ID 번호를 비교합니다. 동일하면 0이 아닌 값이 반환되고, 다르면 0이 반환됩니다.
pthread_t pthread_self(void) 현재 스레드의 스레드 ID를 가져옵니다.
int pthread_create(pthread_t *스레드, const pthread_attr_t *속성,
void *(*시작_루틴) (void *), void *arg);
스레드 예약은 스케줄러의 전략에 따라 다릅니다.
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- printf("thread %ld n",pthread_self());
- return NULL;
- }
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- printf("main %ld n",pthread_self());
-
-
-
- puts("End!");
- }
1. 스레드는 시작 루틴에서 반환되며 반환 값은 스레드의 종료 코드입니다.
2. 스레드는 동일한 프로세스의 다른 스레드에 의해 취소될 수 있습니다.
3. 스레드가 pthread_exit() 함수를 호출합니다. void pthread_exit(void *retval);
int pthread_join(pthread_t thread, void **retval); 프로세스의 대기와 동일하며 시체를 수집하는 데 사용됩니다.
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- pthread_exit(NULL);//线程专用清理函数。
- // return NULL;
- }
-
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- pthread_join(tid,NULL); //收尸
-
- puts("End!");
- }
pthread_cleanup_push(); //atexit와 동일
pthread_cleanup_pop(); //적극적으로 데이터를 가져오는 것과 같습니다.
void pthread_cleanup_push(void (*routine)(void *)는 사전 처리를 보기 위한 gcc -E 매크로의 구현입니다.
무효 *인수);
void pthread_cleanup_pop(intexecute); //호출 여부를 선택합니다.쌍으로 나타나야 하며 매크로로 구현됨
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
-
-
- void cleanup_fun(void*p)
- {
- puts(p);
- }
-
- void* myfunc(void *p)
- {
- puts("Thread is run!");
-
- pthread_cleanup_push(cleanup_fun,"cleanup:1");
- pthread_cleanup_push(cleanup_fun,"cleanup:2");
- pthread_cleanup_push(cleanup_fun,"cleanup:3");
-
- puts("push over!");
-
-
-
- pthread_exit(NULL);//线程专用清理函数。
- // return NULL;
- pthread_cleanup_pop(1) //线程退出后,全部都会调用;
- pthread_cleanup_pop(0);
- pthread_cleanup_pop(1);
- }
-
-
- int main()
- {
- puts("Begin!");
- pthread_t tid;
- int ret;
- ret = pthread_create(&tid,NULL,myfunc ,NULL);
- if(ret)
- {
- fprintf(stderr,"%s n",strerror(ret));
- exit(1);
- }
- pthread_join(tid,NULL); //收尸
-
- puts("End!");
- }
실행 중인 스레드가 시체를 수집하려면 먼저 취소(pthread_cancel)한 후 시체를 수집(pthread_join)해야 합니다.
스레드 취소: int pthread_cancel(pthread_t thread);
취소에는 허용됨과 허용되지 않음의 두 가지 상태가 있습니다.
취소가 허용되지 않음: 코드 실행은 영향을 받지 않고 계속됩니다.
허용되는 취소는 비동기식 취소와 지연된 취소(기본값) -> 취소 지점까지 응답 지연으로 구분됩니다.
취소 지점: Posix에서 정의한 취소 지점은 정체를 일으킬 수 있는 시스템 호출입니다.
pthread_setcancelstate: 취소 상태를 설정할 수 있습니다.
pthread_setcanceltype: 취소 방법을 설정할 수 있습니다.
pthread_testcancel: 이 함수는 아무 작업도 하지 않고 포인트를 취소합니다.
스레드 분리: int pthread_detach(pthread_t thread);
동적 모듈 단일 초기화 함수: int pthread_once(pthread_once_t *once_control,
void (*init_routine)(void));
pthread_once_t once_control = PTHREAD_ONCE_INIT;
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
위의 코드가 실행되면 경쟁이 발생합니다. 매개변수는 주소로 전달되기 때문에 *로 데이터를 검색해야 하며, 이전 스레드가 작업을 수행했는지 여부가 보장되지 않습니다. 가장 간단한 방법은 값 전달을 사용하는 것입니다.
프라이머0.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
프라이머0_e.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- struct thr_arg_st
- {
- int n;
- };
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- struct thr_arg_st* p;
- void *ptr;
- for(i =LEFT;i<=RIGHT;i++)
- {
- p = malloc(sizeof(*p));
- if(p ==NULL)
- {
- perror("malloc");
- exit(1);
- }
- p->n = i;
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,p); // p就是结构体指针就是n的地址
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- //free 不能在这里free,必须取走数据在free
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],&ptr);// 收尸并且接受返回参数。
- free(ptr);
-
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = ((struct thr_arg_st*)p)->n;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(p); //返回值返回p
- return NULL;
- }
추가.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (20)
-
- void* thr_add(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<=THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_add,NULL);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=0;i<=THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
-
- return 0;
- }
-
- void* thr_add(void*p)
- {
- FILE*fp;
- char line_buf[1024];
- int len_size = 1024;
- fp = fopen(FILENAME,"r+");
-
- fgets(line_buf,len_size,fp);
-
- fseek(fp,0,SEEK_SET);
-
- fprintf(fp,"%d n",atoi(line_buf)+1);
-
- fclose(fp);
-
- pthread_exit(NULL);
-
- return NULL;
- }
20개의 스레드가 동시에 파일에서 데이터를 읽고 쓸 때 경쟁과 충돌이 발생할 수 있습니다. 한 스레드가 쓰기 전에 다른 스레드가 마지막 데이터를 읽습니다.
- #include <stdlib.h>
- #include <stdio.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include "mytbf.h"
-
- struct mytbf_st
- {
- int cps;
- int burst;
- int token;
- int pos;
- pthread_mutex_t mut;
- };
- static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
- static pthread_t tid_alrm;
- pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- static struct mytbf_st* job[MYTBF_MAX];
-
- typedef void (*sighandler_t)(int);
-
-
- static int get_free_pos_unlocked(void)
- {
- for(int i=0;i< MYTBF_MAX;i++)
- {
- if(job[i]==NULL)
- return i;
- }
- return -1;
- }
-
- static void* thr_alrm(void*p)
- {
- while(1)
- {
- pthread_mutex_lock(&mut_job);
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i] != NULL)
- {
- pthread_mutex_lock(&job[i]->mut);
- job[i]->token += job[i]->cps;
- if(job[i]->token >job[i]->burst )
- {
- job[i]->token = job[i]->burst;
- }
- pthread_mutex_unlock(&job[i]->mut);
- }
- }
- pthread_mutex_unlock(&mut_job);
- sleep(1);
- }
- return NULL;
- }
-
- static void module_unload()
- {
- pthread_cancel(tid_alrm);
- pthread_join(tid_alrm,NULL);
- //只能一个人掉,二个人调用容易出差
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i]!=NULL)
- {
- mytbf_destroy(job[i]);
- }
- }
- pthread_mutex_destroy(&mut_job);
-
- }
-
- static void module_load()
- {
- int err;
- err = pthread_create(&tid_alrm,NULL,thr_alrm,NULL);
- if(err)
- {
- fprintf(stderr,"create errorn");
- exit(1);
- }
- atexit(module_unload);
- }
-
- mytbf_t* mytbf_init(int cps ,int burst) //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
- {
- struct mytbf_st*me;
- int pos;
- pthread_once(&init_once,module_load); //只初始化一次
- me = malloc(sizeof(*me));
- if(me == NULL)
- return NULL;
-
- me->cps = cps;
- me->burst = burst;
- me->token = 0;
-
- pthread_mutex_init(&me->mut,NULL);
-
- pthread_mutex_lock(&mut_job);
-
- pos = get_free_pos_unlocked();
- if(pos < 0)
- {
-
- pthread_mutex_unlock(&mut_job);
- free(me);
- return NULL;
- }
- me->pos = pos;
- job[pos] = me;
-
- pthread_mutex_unlock(&mut_job);
-
- return me;
-
- }
- int mytbf_fetchtoken(mytbf_t*ptr,int size) //获取token
- {
- if(size <= 0)
- return -EINVAL; //参数非法
- struct mytbf_st*me = ptr;
- pthread_mutex_lock(&me->mut);
- while(me->token <= 0 ) //token为空就等待
- {
- pthread_mutex_unlock(&me->mut);
- sched_yield();
- pthread_mutex_lock(&me->mut);
- }
-
- int n = (me->token>size?size:me->token);
- me->token -= n;
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- int mytbf_returntoken(mytbf_t*ptr,int size) //返还token
- {
- if(size<=0)
- return -EINVAL;
- struct mytbf_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->token+= size;
- if(me->token > me->burst)
- me->token = me->burst;
-
- pthread_mutex_unlock(&me->mut);
- return size;
- }
-
- int mytbf_destroy(mytbf_t*ptr)
- {
- struct mytbf_st *me;
- me = ptr;
- pthread_mutex_lock(&mut_job);
- job[me->pos] = NULL;
- pthread_mutex_unlock(&mut_job);
- pthread_mutex_destroy(&me->mut);
- free(ptr);
- return 0;
-
- }
이는 자물쇠와 동일하며 작동하기 전에 잠금을 해제해야 합니다. (쿼리 방법)
man pthread_mutex_init가 오류를 보고하면 종속성을 설치하십시오.
sudo apt-get install manpages-posix manpages-posix-dev
int pthread_mutex_destroy(pthread_mutex_t *mutex); //잠금을 해제합니다.
int pthread_mutex_init(pthread_mutex_t *뮤텍스 제한,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 정적 초기화
int pthread_mutex_lock(pthread_mutex_t *mutex); //잠금 해제
int pthread_mutex_trylock(pthread_mutex_t *mutex);//잠금을 시도하고 그렇지 않은 경우 실행을 계속합니다.
int pthread_mutex_unlock(pthread_mutex_t *mutex);//잠금 해제
추가.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (20)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
- void* thr_add(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_add,NULL);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
-
- void* thr_add(void*p)
- {
- FILE*fp;
- char line_buf[1024];
- int len_size = 1024;
-
- pthread_mutex_lock(&mut);
-
-
- fp = fopen(FILENAME,"r+");
- fgets(line_buf,len_size,fp);
-
- fseek(fp,0,SEEK_SET);
-
- fprintf(fp,"%d n",atoi(line_buf)+1);
- fclose(fp);
- pthread_mutex_unlock(&mut);
-
- pthread_exit(NULL);
-
- return NULL;
- }
abcd.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
-
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- while(1)
- {
- write(1,&c,1);
- }
-
- pthread_exit(NULL);
-
- return NULL;
- }
abcd.c
체인을 사용하여 잠그거나 잠금을 해제하세요.
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut[THRNUM];
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
- pthread_mutex_init(mut+i,NULL); //初始化四个锁
- pthread_mutex_lock(mut+i);
-
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- pthread_mutex_unlock(mut+0);
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- return 0;
- }
- int next(int n)
- {
- if(n +1 ==THRNUM)
- return 0;
- return n+1;
- }
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- int n = (int)p;
- while(1)
- {
- pthread_mutex_lock(mut+n);
- write(1,&c,1);
- pthread_mutex_unlock(mut+next(n) );
- }
- pthread_exit(NULL);
-
- return NULL;
- }
풀 알고리즘은 소수 계산(쿼리 방식)을 구현합니다.
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =LEFT;i<=RIGHT;i++)
- {
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- // err= pthread_create(tid+(i-LEFT),NULL,thr_prime,&i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
- pthread_exit(NULL);
- return NULL;
- }
통신을 위한 고시법입니다.
int pthread_cond_destroy(pthread_cond_t *조건);
int pthread_cond_init(pthread_cond_t *제한 조건,
const pthread_condattr_t *제한 속성);
pthread_cond_t 조건 = PTHREAD_COND_INITIALIZER;
int pthread_cond_broadcast(pthread_cond_t *cond); //대기 중인 모든 것을 깨웁니다.
int pthread_cond_signal(pthread_cond_t *cond);//대기 상태를 깨우세요
int pthread_cond_timedwait(pthread_cond_t *restrict cond, //시간 초과 대기
pthread_mutex_t *뮤텍스 제한,
const 구조체 시간 지정 *제한 절대시간);
int pthread_cond_wait(pthread_cond_t *제한 조건, //실수 등
pthread_mutex_t *뮤텍스 제한);
mytbf.c (알림 방법)
- #include <stdlib.h>
- #include <stdio.h>
- #include <error.h>
- #include <string.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <signal.h>
- #include <pthread.h>
-
- #include "mytbf.h"
-
- struct mytbf_st
- {
- int cps;
- int burst;
- int token;
- int pos;
- pthread_mutex_t mut;
- pthread_cond_t cond;
-
- };
- static pthread_mutex_t mut_job = PTHREAD_MUTEX_INITIALIZER;
- static pthread_t tid_alrm;
- pthread_once_t init_once = PTHREAD_ONCE_INIT;
-
- static struct mytbf_st* job[MYTBF_MAX];
-
- typedef void (*sighandler_t)(int);
-
-
- static int get_free_pos_unlocked(void)
- {
- for(int i=0;i< MYTBF_MAX;i++)
- {
- if(job[i]==NULL)
- return i;
- }
- return -1;
- }
-
- static void* thr_alrm(void*p)
- {
- while(1)
- {
- pthread_mutex_lock(&mut_job);
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i] != NULL)
- {
- pthread_mutex_lock(&job[i]->mut);
- job[i]->token += job[i]->cps;
- if(job[i]->token >job[i]->burst )
- {
- job[i]->token = job[i]->burst;
- }
- pthread_cond_broadcast(&job[i]->cond);
- pthread_mutex_unlock(&job[i]->mut);
- }
- }
- pthread_mutex_unlock(&mut_job);
- sleep(1);
- }
- return NULL;
- }
-
- static void module_unload()
- {
- pthread_cancel(tid_alrm);
- pthread_join(tid_alrm,NULL);
- //只能一个人掉,二个人调用容易出差
- for(int i=0;i<MYTBF_MAX;i++)
- {
- if(job[i]!=NULL)
- {
- mytbf_destroy(job[i]);
- }
- }
- pthread_mutex_destroy(&mut_job);
-
- }
-
- static void module_load()
- {
- int err;
- err = pthread_create(&tid_alrm,NULL,thr_alrm,NULL);
- if(err)
- {
- fprintf(stderr,"create errorn");
- exit(1);
- }
- atexit(module_unload);
- }
-
- mytbf_t* mytbf_init(int cps ,int burst) //C语言中,void*可以赋值给任何类型的指针,任何类型的指针也都可以赋值给void*
- {
- struct mytbf_st*me;
- int pos;
- pthread_once(&init_once,module_load); //只初始化一次
- me = malloc(sizeof(*me));
- if(me == NULL)
- return NULL;
-
- me->cps = cps;
- me->burst = burst;
- me->token = 0;
-
- pthread_mutex_init(&me->mut,NULL);
- pthread_cond_init(&me->cond,NULL);
- pthread_mutex_lock(&mut_job);
-
- pos = get_free_pos_unlocked();
- if(pos < 0)
- {
-
- pthread_mutex_unlock(&mut_job);
- free(me);
- return NULL;
- }
- me->pos = pos;
- job[pos] = me;
-
- pthread_mutex_unlock(&mut_job);
-
- return me;
-
- }
- int mytbf_fetchtoken(mytbf_t*ptr,int size) //获取token
- {
- if(size <= 0)
- return -EINVAL; //参数非法
- struct mytbf_st*me = ptr;
- pthread_mutex_lock(&me->mut);
- while(me->token <= 0 ) //token为空就等待
- {
- pthread_cond_wait(&me->cond,&me->mut); //解锁等待,等待conad_broadcast和conad_signal的到来
-
- /*
- pthread_mutex_unlock(&me->mut);
- sched_yield();
- pthread_mutex_lock(&me->mut);
- */
- }
-
-
- int n = (me->token>size?size:me->token);
- me->token -= n;
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- int mytbf_returntoken(mytbf_t*ptr,int size) //返还token
- {
- if(size<=0)
- return -EINVAL;
- struct mytbf_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->token+= size;
- if(me->token > me->burst)
- me->token = me->burst;
- pthread_cond_broadcast(&me->cond);
- pthread_mutex_unlock(&me->mut);
- return size;
- }
-
- int mytbf_destroy(mytbf_t*ptr)
- {
- struct mytbf_st *me;
- me = ptr;
- pthread_mutex_lock(&mut_job);
- job[me->pos] = NULL;
- pthread_mutex_unlock(&mut_job);
- pthread_mutex_destroy(&me->mut);
- pthread_cond_destroy(&me->cond);
- free(ptr);
- return 0;
-
- }
프라이머0_풀.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include <sched.h>
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (4)
-
- static int num = 0;
- static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
- static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
-
- for(i =0;i<=THRNUM;i++)
- {
- err= pthread_create(tid+(i),NULL,thr_prime,(void *)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
- //下发任务
- for(i=LEFT;i<RIGHT;i++)
- {
- pthread_mutex_lock(&mut);
- while(num !=0) //不是0就需要等待任务被取走
- {
- pthread_cond_wait(&cond,&mut);
- }
-
- num = i; //下发任务
- pthread_cond_signal(&cond); //下游叫醒任意一个
- pthread_mutex_unlock(&mut);
- }
- pthread_mutex_lock(&mut);
- while(num!= 0)
- {
- pthread_mutex_unlock(&mut);
- sched_yield(); //出让调度器给别的线程
- }
- num = -1; //用于线程退出
- pthread_cond_broadcast(&cond);
-
- pthread_mutex_unlock(&mut);
-
- for(i=0;i<=THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_mutex_destroy(&mut);
- pthread_cond_destroy(&cond);
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
- while(1)
- {
- pthread_mutex_lock(&mut);
- while(num == 0)
- {
- pthread_cond_wait(&cond,&mut);
- }
- if(num == -1)
- {
- pthread_mutex_unlock(&mut); //走到这里必须要解锁。
- break;
- }
-
- i= num;
- num = 0;
- pthread_cond_broadcast(&cond);
-
- pthread_mutex_unlock(&mut);
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("[%d]%d is a primer n",(int)p,i);
- }
-
- pthread_exit(NULL);
- return NULL;
- }
abcd_조건.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
-
- #define FILENAME "/tmp/out"
- #define THRNUM (4)
-
- pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
- pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
- int num;
-
- void* thr_abcd(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
- for(i =0;i<THRNUM;i++)
- {
-
- err= pthread_create(tid+(i),NULL,thr_abcd,(void*)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- alarm(2);
-
- for(i=0;i<THRNUM;i++)
- {
- pthread_join(tid[i],NULL);
- }
- pthread_cond_destroy(&cond);
- pthread_mutex_destroy(&mut);
- return 0;
- }
- int next(int n)
- {
- if(n +1 ==THRNUM)
- return 0;
- return n+1;
- }
- void* thr_abcd(void*p)
- {
- int c = 'a'+ (int)p;
- int n = (int)p;
- while(1)
- {
- pthread_mutex_lock(&mut);
- while(num != n)
- {
- pthread_cond_wait(&cond,&mut);
- }
- write(1,&c,1);
- num = next(num);
- pthread_cond_broadcast(&cond);
- pthread_mutex_unlock(&mut );
- }
- pthread_exit(NULL);
-
- return NULL;
- }
뮤텍스는 bool 유형이고 세마포어는 int 유형입니다. 충분하지 않으면 대기합니다.
마이셈.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
- #include <string.h>
- #include <unistd.h>
- #include "mysem.h"
-
- struct mysem_st
- {
- int value;
- pthread_mutex_t mut;
- pthread_cond_t cond;
-
- };
-
- mysem_t* mysem_init(int initval)
- {
- struct mysem_st*me;
- me = malloc(sizeof(*me));
- if(me==NULL)
- return NULL;
- me->value = initval;
- pthread_mutex_init(&me->mut,NULL);
- pthread_cond_init(&me->cond,NULL);
-
- return me;
-
- }
-
- int mysem_add(mysem_t*ptr ,int n)
- {
- struct mysem_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
-
- me->value+= n;
- pthread_cond_broadcast(&me->cond);
- pthread_mutex_unlock(&me->mut);
-
- return n;
- }
-
- int mysem_sub(mysem_t*ptr ,int n )
- {
- struct mysem_st*me = ptr;
-
- pthread_mutex_lock(&me->mut);
- while(me->value <n)
- {
- pthread_cond_wait(&me->cond,&me->mut);
- }
- me->value -=n;
-
- pthread_mutex_unlock(&me->mut);
- return n;
- }
-
- void mysem_destroy(mysem_t*ptr)
- {
- struct mysem_st*me = ptr;
- pthread_mutex_destroy(&me->mut);
- pthread_cond_destroy(&me->cond);
- free(me);
- }
-
-
-
마이셈.h
- #ifndef MYSEM_H
- #define MYSEM_H
-
- typedef void mysem_t;
-
- mysem_t* mysem_init(int initval);
-
- int mysem_add(mysem_t*,int);
-
- int mysem_sub(mysem_t*,int);
-
- void mysem_destroy(mysem_t*);
-
-
-
- #endif
메인.c
- #include <stdlib.h>
- #include <stdio.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include "mysem.h"
-
- #define LEFT 30000000
- #define RIGHT 30000200
- #define THRNUM (RIGHT-LEFT+1)
-
- #define N 4
- static mysem_t* sem;
-
- void* thr_prime(void*p);
-
- int main()
- {
- pthread_t tid[THRNUM];
- int i,j,mark;
- int err;
-
- sem = mysem_init(N);
- if(sem ==NULL)
- {
- fprintf(stderr,"mysem_init n");
- exit(1);
- }
-
- for(i =LEFT;i<=RIGHT;i++)
- {
- mysem_sub(sem,1);
-
- err= pthread_create(tid+(i-LEFT),NULL,thr_prime,(void *)i);
- if(err)
- {
- fprintf(stderr,"pthread_create():%sn",strerror(err));
- }
- }
-
- for(i=LEFT;i<=RIGHT;i++)
- {
- pthread_join(tid[i-LEFT],NULL);
- }
-
- mysem_destroy(sem);
-
- return 0;
- }
-
- void* thr_prime(void*p)
- {
- int i,j,mark;
-
- i = (int)p;
- // i = *(int*)p;
-
- mark = 1;
- for(j=2;j<i/2;j++)
- {
- if(i%j ==0)
- {
- mark = 0;
- break;
- }
- }
- if(mark)
- printf("%d is a primer n",i);
-
- sleep(5); //ps ax -L 可以观察到对线程进行了限制,只创建了四个线程
-
- mysem_add(sem,1);
- pthread_exit(NULL);
-
- return NULL;
- }
메이크파일
- all:mysem
- CFLAGS+=-g -Wall -pthread
- LDFLAGS+= -pthread
-
- mysem:main.o mysem.o
- gcc $^ $(CFLAGS) $(LDFLAGS) -o $@
-
- clean:
- rm -rf *.o mysem
뮤텍스와 세마포어의 포괄적인 사용. 읽기 잠금(세마포어)과 쓰기 잠금(뮤텍스)으로 구분됩니다. 일반적으로 읽기 및 쓰기에는 상한선을 설정해야 합니다.
작가들이 굶어 죽는 일이 없도록 해야 한다.
pthread_create의 두 번째 매개변수는 스레드의 속성입니다.
int pthread_attr_init(pthread_attr_t *속성);
int pthread_attr_destroy(pthread_attr_t *속성);
테스트 프로그램에서 생성된 최대 스레드 수입니다. ()
- #include <stdlib.h>
- #include <stdio.h>
- #include <pthread.h>
-
- void* func(void)
- {
- int i;
-
- // printf("%pn",&i);
- pthread_exit(NULL);
- return NULL;
- }
-
- int main()
- {
- int err;
- pthread_t tid;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr,1024*1024); //1mb
-
- int i = 0;
- for(;;i++)
- {
- err = pthread_create(&tid,&attr,func,NULL);
- if(err)
- {
- fprintf(stderr,"create errn");
- break;
- }
- }
- printf("max = %d n",i);
- pthread_attr_destroy(&attr);
- return 0;
- }
뮤텍스 속성:
int pthread_mutex 속성_init(pthread_mutex 속성_t * 속성);
pthread_mutexattr_destroy()를 참조하세요.
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, //프로세스 간에 작동
int *p공유);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared);
//파일 설명자 배열을 공유할 수 있는 하위 프로세스를 생성합니다. 공유하지 않도록 선택할 수도 있습니다. Linux에서는 프로세스와 스레드 사이에 구분이 없습니다.
int clone(int (*fn)(void *), void *stack, int 플래그, void *arg, ...
/* pid_t *부모_tid, void *tls, pid_t *자식_tid */);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *제한 속성,
int *제한 유형);
int pthread_mutexattr_settype(pthread_mutexattr_t *속성, int 유형);
조건 변수 속성:
int pthread_condattr_destroy(pthread_condattr_t * 속성);
int pthread_condattr_init(pthread_condattr_t *속성);
읽기-쓰기 잠금 속성:
재진입 기능은 단순히 중단될 수 있는 기능입니다. 즉, 실행 중에 언제든지 이 기능을 중단하고 제어를 반환할 때 오류 없이 다른 코드를 실행하도록 OS 스케줄링으로 전송할 수 있습니다. 함수는 전역 변수 영역, 인터럽트 벡터 테이블 등과 같은 일부 시스템 리소스를 사용하므로 중단되면 이러한 함수는 멀티 태스킹 환경에서 실행되지 않을 수 있습니다.
멀티스레딩의 IO. 잠금 해제된 기능은 (비재진입 기능, 다중 스레드 동시성은 지원되지 않음)로 끝납니다. man putc_unlocked, 지원되지 않는 IO 작업을 확인하세요.
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
int sigwait(const sigset_t *set, int *sig);
int pthread_kill(pthread_t 스레드, int sig);
공식 웹사이트를 참조하세요: www.OpenMp.org
Openmp 구문 태그는 gcc4.0 이후에 지원됩니다.단 몇 개의 CPU로 얼마나 많은 동시성을 달성할 수 있습니까?
안녕하세요.c
- #include <stdio.h>
- #include <stdlib.h>
-
- int main()
- {
- #pragma omp parallel //实现并发
- {
- puts("Hello ");
- puts(" World");
- }
- return 0;
- }
메이크파일
CFLAGS += -Wall -fopenmp
Hello를 컴파일하고 실행해 보세요.
- #include <stdio.h>
- #include <stdlib.h>
- #include <omp.h>
-
- int main()
- {
- #pragma omp parallel sections
- {
- #pragma omp section
- printf("[%d:]Hello n",omp_get_thread_num() );
- #pragma omp section
- printf("[%d:]World n",omp_get_thread_num() );
- }
- return 0;
- }