[리눅스 프로그래밍] 멀티 스레드

Yoon Yeoung-jin·2022년 6월 19일
0

Linux

목록 보기
3/13

Single-thread vs Multi-thread

  • code, data, file 데이터는 여러개의 스레드에서 공유되는 자원이다.
  • register, stack 영역의 데이터는 각 스레드마다 독립적으로 사용된다.
  • Single-thread로 사용하는 것 보다 Multi-thread가 성능이 훨씬 좋다.
  • 다만 Multi-thread를 사용할때 각 스레드가 사용되는 공유 자원 관리가 매우 중요하다. (critical section)

사용 헤더

  • pthread.h
  • makefile: CFLAGS에 -pthread 옵션 필수

사용 함수

  • pthread_create : 스레드 생성해주는 함수
    int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                              void *(*start_routine) (void *), void *arg);
    파라미터
    - thread: 생성된 thread ID
    - attr: 쓰레드 속성(pthread_attr_init()으로 초기화)
    - start_routine: thread main function
    - arg: thread main function 호출 시 사용할 파라미터
    반환값
    - 성공: 0
    - 실패: errno를 리턴
  • pthread_exit: 스레드 종료 함수
    void pthread_exit(void *retval); 
    파라미터
    - retval: exit status를 저장
  • pthread_join: 스레드 종료를 기다리는 함수
    int pthread_join(pthread_t thread, void **retval); 
    파라미터
    - thread: 기다릴 thread ID
    - retval: 해당 thread의 exit status를 저장
    반환값
    - 성공시0
    - 실패시 errno를 리턴
  • pthread_detach: pthread_join을 사용하지 않더라도, ㅅ레드 종료될때 모든 자원을 해제한다.
    int pthread_detach(pthread_t thread);
    파라미터
    - thread: 떼어낼 thread ID
    반환값
    - 성공시0
    - 실패시 errno를 리턴
  • pthread_mutex_init: mutex 객체 초기화
    int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    파라미터
    - mutex: mutex instance
    - attr: mutex 속성
    반환값
    - 성공시0
    - 실패시 errno를 리턴
  • pthread_mutex_destroy: mutex 객체 free
    int pthread_mutex_destroy(pthread_mutex_t *mutex);
    파라미터
    - mutex: mutex instance
    반환값
    - 성공시0
    - 실패시 errno를 리턴
  • pthread_mutex_lock, trylock, unlock
    int pthread_mutex_lock(pthread_mutex_t *mutex);
    int pthread_mutex_trylock(pthread_mutex_t *mutex);
    int pthread_mutex_unlock(pthread_mutex_t *mutex);
    
    파라미터
    - mutex: mutex instance
    반환값
    - 성공시0
    - 실패시 errno를 리턴

예제 코드

/**
 * @file main.c
 * @author Yeoung jin Yoon (alwns28@kookmin.ac.kr)
 * @brief pthread 예시 프로그램
 * @version 0.1
 * @date 2022-06-25
 * 
 * @copyright Copyright (c) 2022
 * 
 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<pthread.h>

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<errno.h>

#define MAX_NUM 100
#define PLUS_NUM 10
#define FILE_PATH "pthread_debug.txt"

pthread_mutex_t share_memory_control;
int share_memory = 0;

void *count_share_memory(void *arg)
{
    int fd = 0;
    for(int i=0; i<MAX_NUM; i++){
        pthread_mutex_lock(&share_memory_control);
        fd = open((const char *)FILE_PATH, O_CREAT | O_APPEND | O_RDWR, 0644);
        if(fd == -1){
            printf("open() fail: %s\n", strerror(errno));
            exit(0);
        }
        dprintf(fd, "[Child ID: %lu] share_memory: %d\n", pthread_self(), share_memory);
        close(fd);
        share_memory++;
        sleep(1);
        pthread_mutex_unlock(&share_memory_control);
    }
}

void *plus_share_memory(void *arg)
{
    int fd = 0;
    for(int i=0; i<10; i++){
        pthread_mutex_lock(&share_memory_control);
        fd = open((const char *)FILE_PATH, O_CREAT | O_APPEND | O_RDWR, 0644);
        if(fd == -1){
            printf("open() fail: %s\n", strerror(errno));
            exit(0);
        }
        dprintf(fd, "[Child ID: %lu] share_memory: %d\n", pthread_self(), share_memory);
        share_memory += (int)PLUS_NUM;
        close(fd);
        pthread_mutex_unlock(&share_memory_control);
        sleep(3);
    }
}

int main(int argc, char **argv)
{
    pthread_t pthread_list[2];
    int ret = 0;

    if(pthread_mutex_init(&share_memory_control, NULL)){
        printf("pthread_mutex_init fail: %s\n", strerror(errno));
        return -1;
    }

    printf("[MAIN] Thread id: %lu\n", pthread_self());

    ret = pthread_create(&pthread_list[0], NULL, count_share_memory, NULL);
    if(ret){
        printf("pthread_create fail: %s\n", strerror(errno));
        return -1;
    }
    ret = pthread_create(&pthread_list[1], NULL, plus_share_memory, NULL);
    if(ret){
        printf("pthread_create fail: %s\n", strerror(errno));
        return -1;
    }

    printf("trying to join %lu\n", pthread_list[0]);
    if(pthread_join(pthread_list[0], NULL)){
        printf("pthread_join(%lu) fail\n",pthread_list[0]);
    }

    printf("trying to join %lu\n", pthread_list[1]);
    if(pthread_join(pthread_list[1], NULL)){
        printf("pthread_join(%lu) fail\n",pthread_list[0]);   
    }
    

    if(pthread_detach(pthread_list[0]) != 0){
        printf("pthread_detach 0 fail: %s\n", strerror(errno));
        return -1;
    }
    if(pthread_detach(pthread_list[1]) != 0){
        printf("pthread_detach 1 fail: %s\n", strerror(errno));
        return -1;
    }

    if(pthread_mutex_destroy(&share_memory_control) != 0){
        printf("pthread_mutex_destroy fail: %s\n", strerror(errno));
        return -1;
    }

    return 0;
}
profile
신기한건 다 해보는 사람

0개의 댓글