>운영 및 유지보수 >리눅스 운영 및 유지 관리 >Linux 다중 스레드 프로그래밍 예제 코드 분석

Linux 다중 스레드 프로그래밍 예제 코드 분석

王林
王林앞으로
2023-05-26 22:04:041574검색

먼저 예를 들어보겠습니다. 숫자를 증가시키기 위해 두 개의 스레드를 만듭니다. 이 예는 실용적인 가치가 없을 수도 있지만 약간만 변경하면 다른 곳에서도 사용할 수 있습니다.

코드:

/*thread_example.c : c multiple thread programming in linux
 *author : falcon
 *e-mail : tunzhj03@st.lzu.edu.cn
 */
#include <pthread.h>
#include <stdio.h>
#include <sys/time.h>
#include <string.h>
#define max 10

pthread_t thread[2];
pthread_mutex_t mut;
int number=0, i;

void *thread1()
{
    printf ("thread1 : i&#39;m thread 1/n");

    for (i = 0; i < max; i++)
    {
        printf("thread1 : number = %d/n",number);
        pthread_mutex_lock(&mut);
            number++;
        pthread_mutex_unlock(&mut);
        sleep(2);
    }


    printf("thread1 :主函数在等我完成任务吗?/n");
    pthread_exit(null);
}

void *thread2()
{
    printf("thread2 : i&#39;m thread 2/n");

    for (i = 0; i < max; i++)
    {
        printf("thread2 : number = %d/n",number);
        pthread_mutex_lock(&mut);
            number++;
        pthread_mutex_unlock(&mut);
        sleep(3);
    }


    printf("thread2 :主函数在等我完成任务吗?/n");
    pthread_exit(null);
}

void thread_create(void)
{
    int temp;
    memset(&thread, 0, sizeof(thread));     //comment1
    /*创建线程*/
    if((temp = pthread_create(&thread[0], null, thread1, null)) != 0) //comment2   
        printf("线程1创建失败!/n");
    else
        printf("线程1被创建/n");

    if((temp = pthread_create(&thread[1], null, thread2, null)) != 0) //comment3
        printf("线程2创建失败");
    else
        printf("线程2被创建/n");
}

void thread_wait(void)
{
    /*等待线程结束*/
    if(thread[0] !=0)      {       //comment4          pthread_join(thread[0],null);
        printf("线程1已经结束/n");
     }
    if(thread[1] !=0)      {         //comment5        pthread_join(thread[1],null);
        printf("线程2已经结束/n");
     }
}

int main()
{
    /*用默认属性初始化互斥锁*/
    pthread_mutex_init(&mut,null);

    printf("我是主函数哦,我正在创建线程,呵呵/n");
    thread_create();
    printf("我是主函数哦,我正在等待线程完成任务阿,呵呵/n");
    thread_wait();

    return 0;
}

먼저 컴파일하고 실행해 보겠습니다.

인용:

falcon@falcon:~/program/c/code/ftp$ gcc -lpthread -o thread_example thread_example.c
falcon@falcon:~/program/c/code/ftp$ ./thread_example
我是主函数哦,我正在创建线程,呵呵
线程1被创建
线程2被创建
我是主函数哦,我正在等待线程完成任务阿,呵呵
thread1 : i&#39;m thread 1
thread1 : number = 0
thread2 : i&#39;m thread 2
thread2 : number = 1
thread1 : number = 2
thread2 : number = 3
thread1 : number = 4
thread2 : number = 5
thread1 : number = 6
thread1 : number = 7
thread2 : number = 8
thread1 : number = 9
thread2 : number = 10
thread1 :主函数在等我完成任务吗?
线程1已经结束
thread2 :主函数在等我完成任务吗?
线程2已经结束

이제 위 소개와 관련된 여러 함수와 변수를 인터넷에서 인용하겠습니다.

인용:

스레드 관련 작업

一 pthread_t

pthread_t는 /usr/include/bits/pthreadtypes.h 헤더 파일에 정의되어 있습니다.
 typedef unsigned long int pthread_t;
 스레드의 식별자입니다.

두 번째 pthread_create

pthread_create 함수는 스레드를 생성하는 데 사용됩니다. 해당 프로토타입은 다음과 같습니다.
 extern int pthread_create __p ((pthread_t *__thread, __const pthread_attr_t *__attr,
 void *(*__start_routine) (void *), void * __arg ));
첫 번째 매개변수는 스레드 식별자에 대한 포인터이고, 두 번째 매개변수는 스레드 속성을 설정하는 데 사용되며, 세 번째 매개변수는 스레드 실행 함수의 시작 주소이고, 마지막 매개변수는 실행 매개변수입니다. 기능. 여기서 함수 스레드에는 매개변수가 필요하지 않으므로 마지막 매개변수는 널 포인터로 설정됩니다. 또한 두 번째 매개변수를 널 포인터로 설정하여 기본 속성을 가진 스레드를 생성합니다. 다음 섹션에서는 스레드 속성의 설정 및 수정에 대해 설명하겠습니다. 스레드가 성공적으로 생성되면 함수는 0을 반환합니다. 0이 아니면 스레드 생성이 실패합니다. 일반적인 오류 반환 코드는 eagain 및 einval입니다. 전자는 시스템이 새로운 스레드 생성을 제한한다는 것을 의미합니다. 예를 들어 스레드 수가 너무 많다는 것은 두 번째 매개변수가 나타내는 스레드 속성 값이 불법임을 의미합니다. 스레드가 성공적으로 생성된 후 새로 생성된 스레드는 매개변수 3과 매개변수 4에 의해 결정된 함수를 실행하고 원래 스레드는 계속해서 다음 코드 줄을 실행합니다.

3개의 pthread_join pthread_exit
 
pthread_join 함수는 스레드의 끝을 기다리는 데 사용됩니다. 함수 프로토타입은 다음과 같습니다.
 extern int pthread_join __p ((pthread_t __th, void **__thread_return));
 첫 번째 매개변수는 대기할 스레드 식별자이고, 두 번째 매개변수는 사용할 수 있는 사용자 정의 포인터입니다. 기다리고 있는 스레드의 반환 값을 저장합니다. 이 함수는 스레드 차단 함수입니다. 이를 호출하는 함수는 대기 스레드가 끝날 때까지 대기합니다. 함수가 반환되면 대기 스레드의 리소스가 복구됩니다. 스레드를 종료하는 방법에는 두 가지가 있습니다. 하나는 위의 예와 같으며, 함수가 종료되면 이를 호출한 스레드도 종료됩니다. 함수 프로토타입은 다음과 같습니다.
extern void pthread_exit __p ((void *__retval)) __attribute__ ((__noreturn__));
유일한 매개 변수는 pthread_join의 두 번째 매개 변수 thread_return이 null이 아닌 한 함수의 반환 코드입니다. 값은 thread_return으로 전달됩니다. 마지막으로 주의할 점은 여러 스레드가 하나의 스레드를 기다릴 수 없다는 것입니다. 그렇지 않으면 신호를 수신한 첫 번째 스레드가 성공적으로 반환되고 pthread_join을 호출하는 나머지 스레드는 오류 코드 esrch를 반환합니다.
 이 섹션에서는 가장 간단한 스레드를 작성하고 가장 일반적으로 사용되는 세 가지 함수인 pthread_create, pthread_join 및 pthread_exit를 마스터했습니다. 다음으로 스레드의 몇 가지 일반적인 속성과 이를 설정하는 방법을 살펴보겠습니다.

Mutex 잠금 관련

Mutex 잠금은 일정 시간 내에 하나의 스레드만 코드 조각을 실행하도록 하는 데 사용됩니다.

一 pthread_mutex_init

pthread_mutex_init 함수는 뮤텍스 잠금을 생성하는 데 사용됩니다. null 매개변수는 기본 속성이 사용됨을 나타냅니다. 특정 속성에 대한 뮤텍스를 선언해야 하는 경우 pthread_mutexattr_init 함수를 호출해야 합니다. pthread_mutexattr_setpshared 함수와 pthread_mutexattr_settype 함수는 뮤텍스 잠금 속성을 설정하는 데 사용됩니다. 이전 함수는 pthread_process_private 및 pthread_process_shared의 두 값을 갖는 pshared 속성을 설정합니다. 전자는 서로 다른 프로세스의 스레드를 동기화하는 데 사용되고 후자는 이 프로세스에서 서로 다른 스레드를 동기화하는 데 사용됩니다. 위의 예에서는 기본 속성 pthread_process_private을 사용하고 있습니다. 후자는 뮤텍스 잠금 유형을 설정하는 데 사용됩니다. 선택적 유형은 pthread_mutex_normal, pthread_mutex_errorcheck, pthread_mutex_recursive 및 pthread _mutex_default입니다. 이들은 각각 다른 목록 및 잠금 해제 메커니즘을 정의합니다. 일반적인 상황에서는 마지막 기본 속성이 선택됩니다.

두 개의 pthread_mutex_lock pthread_mutex_unlock pthread_delay_np

pthread_mutex_lock 문은 뮤텍스 잠금으로 잠기기 시작합니다. 후속 코드는 pthread_mutex_unlock이 호출될 때까지 잠깁니다. 즉, 동시에 하나의 스레드에서만 호출하고 실행할 수 있습니다. 스레드가 pthread_mutex_lock을 실행할 때 이때 다른 스레드가 잠금을 사용하고 있으면 해당 스레드는 차단됩니다. 즉, 프로그램은 다른 스레드가 뮤텍스 잠금을 해제할 때까지 대기합니다.

참고:

1 위의 두 가지 휴면은 데모 목적일 뿐만 아니라 스레드가 일정 시간 동안 휴면 상태를 유지하여 스레드가 뮤텍스 잠금을 해제하고 다른 스레드가 이 잠금을 사용할 때까지 기다릴 수 있도록 하기 위한 것입니다. 이 문제는 아래 참고문헌 1에 설명되어 있습니다. 그런데 Linux에는 pthread_delay_np 함수가 없는 것 같아서(해봤는데 정의된 함수에 대한 참조가 없다는 메시지가 표시됨) 대신 sleep을 사용했습니다. 그러나 참조 2에는 다른 방법이 나와 있는 것 같습니다. 이를 달성하는 방법을 제공하는 pthread_cond_timedwait로 대체되었습니다.

2 안에 있는 댓글 1~5를 주목해 주세요. 그것이 제가 알아내는 데 몇 시간이 걸린 문제입니다.
comment1, comment4, comment5가 없으면 pthread_join 시 segfault가 발생하므로, 위의 comment2, comment3이 근본 원인이므로 반드시 전체 코드를 작성해 주시기 바랍니다. 위의 스레드가 성공적으로 생성되지 않을 수 있으므로 스레드가 끝날 때까지 기다릴 수 없으며 pthread_join 사용 시 분할 오류(알 수 없는 메모리 영역에 접근)가 발생합니다. 게다가 memset을 사용할 때 string.h 헤더 파일을 포함시켜야 합니다

위 내용은 Linux 다중 스레드 프로그래밍 예제 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제