#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>

void *thread(void *argument) {
    int thread_num = *(int *)argument;
    printf("Thread #%d: PID = %d, TID = %lu\n", thread_num, getpid(), pthread_self());
    pthread_exit(NULL);
}

int main(void) {
    pthread_t threads[5];
    int thread_args[5];

    for (int i = 0; i < 5; i++) {
        thread_args[i] = i;
        pthread_create(&threads[i], NULL, thread, &thread_args[i]);
    }

    for (int i = 0; i < 5; i++) {
        pthread_join(threads[i], NULL);
        printf("Thread #%lu is terminated.\n", threads[i]);
    }

    return 0;
}

#include <stdio.h>       // 표준 입출력 라이브러리
#include <pthread.h>     // POSIX 스레드 라이브러리
#include <stdlib.h>      // 표준 라이브러리 (malloc, atoi 등)

// 공유 변수와 동기화를 위한 뮤텍스 선언
volatile long int counter = 0;  // 스레드 간 공유되는 카운터
pthread_mutex_t mutex;          // 뮤텍스 변수
int limit;                      // 각 스레드가 반복할 횟수

// 스레드가 실행할 함수
void *worker(void *a) {
    for (int i = 0; i < limit; ++i) {       // limit 횟수만큼 반복
        pthread_mutex_lock(&mutex);         // 뮤텍스 잠금 (임계 영역 보호)
        counter++;                          // 공유 변수 counter 증가
        pthread_mutex_unlock(&mutex);       // 뮤텍스 잠금 해제
    }
    pthread_exit(NULL);                     // 스레드 종료
}

int main(int argc, char *argv[]) {
    pthread_t *tid;                // 스레드 ID를 저장할 배열
    int numTh = atoi(argv[1]);     // 첫 번째 인자: 생성할 스레드 개수
    limit = atoi(argv[2]);         // 두 번째 인자: 각 스레드의 반복 횟수

    tid = malloc(sizeof(pthread_t) * numTh); // 스레드 ID 배열 동적 할당

    // 스레드 생성
    for (int i = 0; i < numTh; ++i)
        pthread_create(&tid[i], NULL, worker, NULL);

    // 스레드 종료 대기
    for (int i = 0; i < numTh; ++i)
        pthread_join(tid[i], NULL);

    // 최종 결과 출력
    printf("Result: %ld\n", counter);

    pthread_mutex_destroy(&mutex); // 뮤텍스 제거
    free(tid);                    // 동적 할당된 메모리 해제

    return 0;
}