programing

Linux에서 pthread_exit()을 사용할 때와 pthread_join()을 사용할 때?

goodcopy 2022. 8. 1. 21:57
반응형

Linux에서 pthread_exit()을 사용할 때와 pthread_join()을 사용할 때?

나는 pthreads를 처음 접해서 그것을 이해하려고 노력하고 있다.나는 다음과 같은 예를 보았다.

걸 알 수 있었어요.main()되었습니다.pthread_exit()되어 있는 를 본 이 있습니다.pthread_join()언제 할 수 을 사용하다

https://computing.llnl.gov/tutorials/pthreads/ 사이트를 참조하고 있습니다.언제 사용할지 개념이 잡히지 않습니다.pthread_join() 사용 pthread_exit()

누가 설명 좀 해줄래?또한 pthreads에 대한 좋은 튜토리얼 링크를 주시면 감사하겠습니다.

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS     5

void *PrintHello(void *threadid)
{
   long tid;
   tid = (long)threadid;
   printf("Hello World! It's me, thread #%ld!\n", tid);
   pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t threads[NUM_THREADS];
   int rc;
   long t;
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: creating thread %ld\n", t);
      rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }

   /* Last thing that main() should do */
   pthread_exit(NULL);

한 가지 더 깨달았어요

pthread_cancel(thread);
pthread_join(thread, NULL);

스레드가 실행되는 동안 스레드를 취소해야 할 수도 있습니다.pthread_cancel(thread);을 사용하여 이를 수행할 수 있습니다.단, pthread 취소 지원을 활성화해야 합니다.또한, 취소 시 정리 코드.

thread_cleanup_push(my_thread_cleanup_handler, resources);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);

static void my_thread_cleanup_handler(void *arg)
{
  // free
  // close, fclose
}

openpub 문서에서 설명한 바와 같이

pthread_exit() 는 호출한 스레드를 종료합니다.

메인 스레드가 호출되기 때문에 메인 스레드는 종료되지만 생성된 스레드는 계속 실행됩니다.이는 주로 메인 스레드가 스레드를 생성하고 스레드가 작업을 수행하도록 하는 데만 필요한 경우에 사용됩니다.

pthread_join 대상 스레드가 종료되지 않는 한 호출한 스레드의 실행을 일시 중지합니다.

이것은 메인 스레드에서 처리를 진행하기 전에 스레드가 종료되기를 기다리는 경우에 유용합니다.

pthread_exit() API

이미 언급했듯이, 는 발신 스레드 종료에 사용됩니다.그 함수에 대한 호출 후 복잡한 정리 메커니즘이 시작됩니다.완료되면 스레드는 종료됩니다.pthread_exit() API는 pthread_create()에 의해 작성된 스레드에서 return() 루틴에 대한 호출이 발생했을 때도 암묵적으로 호출됩니다.실제로 return() 호출과 pthread_exit() 호출은 pthread_create()에 의해 작성된 스레드에서 호출되어 동일한 영향을 미칩니다.

main() 함수가 시작될 때 암묵적으로 작성된 초기 스레드와 pthread_create()에 의해 작성된 스레드를 구별하는 것이 매우 중요합니다.main() 함수에서return() 루틴으로 콜하면 exit() 시스템콜이 암묵적으로 호출되어 프로세스 전체가 종료됩니다.스레드 정리 메커니즘이 시작되지 않았습니다.main() 함수에서 pthread_exit()에 호출하면 청소 메커니즘이 시작되고 작업이 완료되면 초기 스레드가 종료됩니다.

pthread_exit()이 main() 함수에서 호출되었을 때 프로세스 전체(및 다른 스레드)에 발생하는 작업은 PTHREAD 구현에 따라 달라집니다.예를 들어 IBM OS/400 구현에서는 pthread_exit()이 main() 함수에서 호출되면 다른 스레드를 포함한 전체 프로세스가 종료됩니다.다른 시스템은 다르게 동작할 수 있습니다.대부분의 최신 Linux 머신에서는 초기 스레드에서 pthread_exit()에 호출해도 모든 스레드가 종료될 때까지 프로세스 전체가 종료되지 않습니다.휴대용 응용 프로그램을 쓰는 경우 main()의 pthread_exit()을 사용할 때 주의하십시오.

pthread_join() API

스레드 종료를 기다리는 편리한 방법입니다.pthread_join()을 사용하는 대신 스레드 종료를 기다리는 함수를 직접 작성할 수 있습니다.예를 들어, 조건부 변수 대기에 기반한 함수일 수 있습니다.

는 David R의 책을 읽는 것을 추천한다. 부텐호프 "POSIX 스레드를 사용한 프로그래밍"논의된 토픽(및 더 복잡한 것)에 대해 매우 잘 설명하고 있습니다(단, 주요 함수의 pthread_exit 사용법 등 일부 구현 세부 사항은 항상 책에 반영되지는 않습니다).

pthread_exit는, 발신 만, 「」를 참조해 주세요.pthread_join는, 타겟 스레드의 실행이 완료될 때까지, 발신측의 스레드의 실행을 일시정지합니다.

이러한 내용은 오픈 그룹 문서에 자세히 설명되어 있습니다.

두 방법 모두 프로세스가 모든 스레드가 종료되기 에 종료되지 않도록 합니다.

에는 '하다'라는 .main함수는 "실행"될 모든 스레드를 명시적으로 기다립니다.

pthread_exit됩니다.main기능과 스레드가 제어된 방식으로 제공됩니다. mainmain그렇지 않으면 다른 모든 스레드를 포함한 모든 프로세스가 종료됩니다.

중를 사용하는 해야 합니다.main 방법이 좋다는 입니다.main 스레드가 되었기 때문에 를 알 예를 들어, 다른 스레드 자체가 새로운 스레드를 생성했기 때문에main아무것도 몰라요

「」를 사용합니다.pthread_exit) pthread_join하지 않는는 메인 스레드를 사용하지 않는 상태로 둡니다.「」를 하지 않기 에, 「」를 해 주세요.pthread_join종료된 다른 가입 가능한 스레드도 좀비 상태로 남아 리소스 누수의 원인이 됩니다.

결합 가능한 스레드(즉, 분리되지 않은 스레드)와 결합하지 못하면 "좀비 스레드"가 생성됩니다.각 좀비 스레드는 일부 시스템리소스를 소비하기 때문에 좀비 스레드가 충분히 축적되면 새로운 스레드(또는 프로세스)를 작성할 수 없게 되므로 이를 피하십시오.

또 다른 포인트는 메인 스레드를 사용하지 않는 상태로 유지하는 것입니다.다른 스레드가 실행 중일 경우 리소스가 메인 스레드에 할당되어 있는지, 메인 스레드에 로컬인 변수가 다른 스레드에 사용되는지 등 다양한 조건에서 구현에 의존적인 문제가 발생할 수 있습니다.

또한 모든 공유 리소스는 프로세스가 종료될 때만 해제되며 리소스를 절약할 수 없습니다.저는 '아예'를 pthread_exitpthread_join피해야 합니다.

특정 코드로의 콜은 필요 없습니다.

「」의main스레드가 호출되지 않음pthread_exit하지만 다른 스레드가 완료될 때까지 대기하기 위해 종종 전화를 걸어야 합니다.

고객님의 고객명PrintHello함수는요, 안 불러도 안 불러도 돼요.pthread_exit왜냐하면 거기서 돌아온 후 암묵적이기 때문입니다.

따라서 코드는 다음과 같습니다.

void *PrintHello(void *threadid)  {
  long tid = (long)threadid;
  printf("Hello World! It's me, thread #%ld!\n", tid);
  return threadid;
}

int main (int argc, char *argv[]) {
   pthread_t threads[NUM_THREADS];
   int rc;
   intptr_t t;
   // create all the threads
   for(t=0; t<NUM_THREADS; t++){
     printf("In main: creating thread %ld\n", (long) t);
     rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
     if (rc) { fprintf(stderr, "failed to create thread #%ld - %s\n",
                                (long)t, strerror(rc));
               exit(EXIT_FAILURE);
             };
   }
   pthread_yield(); // useful to give other threads more chance to run
   // join all the threads
   for(t=0; t<NUM_THREADS; t++){
      printf("In main: joining thread #%ld\n", (long) t);
      rc = pthread_join(&threads[t], NULL);
      if (rc) { fprintf(stderr, "failed to join thread #%ld - %s\n",
                                (long)t, strerror(rc));
               exit(EXIT_FAILURE);
      }
   }
}

pthread_exit()는 호출 스레드를 종료하고 종료합니다(단, 호출 스레드가 메인 스레드에서 분리되지 않은 경우 호출 스레드에 사용되는 리소스는 운영체제로 해방되지 않습니다).

pthrade_join()는 타겟 스레드가 종료되지 않을 때까지 콜스레드를 대기 또는 차단합니다.간단히 말하면 타깃스레드를 종료할 때까지 기다립니다.

sleep을 sleep(슬립)으로 PrintHellopthread_exit()및가 될 수 ,PrintHello이치노 종료됩니다.사용하시는 경우pthrade_join()를 호출하기 pthread_exit()스레드가 .PrintHello

음.

POSIX pthread_exithttp://pubs.opengroup.org/onlinepubs/009604599/functions/pthread_exit.html에서 설명:

After a thread has terminated, the result of access to local (auto) variables of the thread is 
undefined. Thus, references to local variables of the exiting thread should not be used for 
the pthread_exit() value_ptr parameter value.

이는 로컬 main() 스레드 변수에 액세스할 수 있다는 생각과는 반대되는 것으로 보입니다.

pthread_exit()가 호출되면 발신 스레드스택은 다른 스레드의 "액티브" 메모리로 주소 지정할 수 없게 됩니다."static" 메모리 할당의 .data, .text 및 .bss 부분은 다른 모든 스레드에서 사용할 수 있습니다.따라서 다른 pthread_join() 발신자가 보기 위해 메모리 값을 pthread_exit()에 전달해야 할 경우 pthread_join()을 호출하는 스레드가 사용할 수 있어야 합니다.pthread_join 스레드스택에 malloc()/new를 할당하고 1) pthread_join 발신자가 pthread_create에 전달한 스택 값 또는 pthread_exit()을 호출하는 스레드에 사용할 수 있도록 합니다.

스레드 스택 간의 메모리 관리 방법과 프로세스 전체의 값을 저장하기 위해 사용되는 .data/.bss 메모리 섹션에 값을 저장하는 방법을 이해하는 것이 중요합니다.

  #include<stdio.h>
  #include<pthread.h>
  #include<semaphore.h>
 
   sem_t st;
   void *fun_t(void *arg);
   void *fun_t(void *arg)
   {
       printf("Linux\n");
       sem_post(&st);
       //pthread_exit("Bye"); 
       while(1);
       pthread_exit("Bye");
   }
   int main()
   {
       pthread_t pt;
       void *res_t;
       if(pthread_create(&pt,NULL,fun_t,NULL) == -1)
           perror("pthread_create");
       if(sem_init(&st,0,0) != 0)
           perror("sem_init");
       if(sem_wait(&st) != 0)
           perror("sem_wait");
       printf("Sanoundry\n");
       //Try commenting out join here.
       if(pthread_join(pt,&res_t) == -1)
           perror("pthread_join");
       if(sem_destroy(&st) != 0)
           perror("sem_destroy");
       return 0;
   }

이 코드를 복사하여 gdb에 붙여넣습니다.Onlinegdb는 작동하며 직접 확인할 수 있습니다.

스레드를 작성하면 프로세스가 메인 프로세스와 동시에 실행된다는 것을 이해해야 합니다.

  1. 결합을 사용하지 않으면 메인 스레드가 계속 실행되고 0을 반환합니다.
  2. Join을 사용하면 메인스레드는 스레드의 실행이 완료될 때까지 대기하기 때문에 while loop에 고정됩니다.
  3. pthread_exit에 코멘트를 붙여 삭제하면 루프를 실행하기 전에 스레드가 종료되고 메인 루프가 계속됩니다.
  4. pthread_exit를 실제로 사용하면 종료하기 전에 몇 가지 코드의 1가지 버전이 실행되도록 하기 위해 if 조건 또는 케이스 스테이트먼트로 사용할 수 있습니다.
void *fun_t(void *arg)
   {
       printf("Linux\n");
       sem_post(&st); 
       if(2-1 == 1)  
           pthread_exit("Bye");
       else
       { 
           printf("We have a problem. Computer is bugged");
           pthread_exit("Bye"); //This is redundant since the thread will exit at the end
                                //of scope. But there are instances where you have a bunch
                                //of else if here.
       }
   }

이 예에서는 먼저 세마포를 사용하여 코드 세그먼트를 실행해야 하는 경우가 있습니다.

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

sem_t st;

void* fun_t (void* arg)
{
    printf("I'm thread\n");
    sem_post(&st);
}

int main()
{
    pthread_t pt;
    pthread_create(&pt,NULL,fun_t,NULL);
    sem_init(&st,0,0);
    sem_wait(&st);
    printf("before_thread\n");
    pthread_join(pt,NULL);
    printf("After_thread\n");
    
}

"before thread" 후에 fun_t가 어떻게 실행되고 있는지 알아챘습니다.위에서 아래로 선형일 경우 예상되는 출력은 스레드 전, 스레드 후입니다.단, 이 상황에서는 세마포어가 func_t에 의해 해제될 때까지 메인 동작을 차단합니다.결과는 https://www.onlinegdb.com/ 에서 확인할 수 있습니다.

언급URL:https://stackoverflow.com/questions/20824229/when-to-use-pthread-exit-and-when-to-use-pthread-join-in-linux

반응형