251026

lililllilillll·2025년 10월 26일

개발 일지

목록 보기
336/350

✅ 한 것들


  • 정글 동기 모임에서 포폴 피드백 받음
    • 인턴십이 더 중요 : 매출 낸거 아니면 출시보다도 중요
    • 포폴 형식
      • 한 목적
      • 한 것
      • 한 것에 대한 증거 (사진이나 영상)
    • 줄글로 적으면 글이 너무 많아서 안 봄
    • 너무 기초적인 건 의미없으니 적지 마라
    • 문장은 간결하게. 한 줄로 축약할 수 있는 부분은 줄여라.
    • 어떤 식으로 활용했다 정도가 필요할 때나 코드 스크린샷
    • 유튜브 영상 있는거 확실히 알게 보여줘야 함
  • 윤성우의 열혈 TCP/IP 소켓 프로그래밍


📖 윤성우의 열혈 TCP/IP 소켓 프로그래밍


Chapter 18 멀티쓰레드 기반의 서버구현

18-1 쓰레드의 이론적 이해

멀티프로세스 기반 단점

  • 프로세스 생성 비싸다
  • 프로세스 사이 데이터 교환 IPC 번거롭다
  • (가장 큼) 컨텍스트 스위칭이 일어난다

쓰레드

  • 데이터, 힙 영역은 공유
  • 스택 영역만 별도

프로세스 : 운영체제 관점에서 별도의 실행흐름을 구성하는 단위
쓰레드 : 프로세스 관점에서 별도의 실행흐름을 구성하는 단위

18-2 쓰레드의 생성 및 실행

POSIX(Portable Operating System Interface for Computer Environment)
: UNIX 계열 운영체제 간에 이식성을 높이기 위한 표준 API 규격.
쓰레드 생성 방식도 POSIX 표준 근거.

쓰레드는 별도 실행흐름을 갖기 때문에, 쓰레드만의 main 함수 필요
pthread_create() : 특정 함수를 시작으로 별도 실행흐름 형성할 것을 운영체제에 요청

int main(int argc, char *argv[])
{
	pthread_t t_id;
	int thread_param=5;

	if(pthread_create(&t_id, NULL, thread_main, (void*)&thread_param)!=0)
	{
		puts("pthread_create() error");
		return -1;
	};
	sleep(10); puts("end of main");
	return 0;
}

void* thread_main(void *arg)
{
	int i;
	int cnt=*((int*)arg);
	for(i=0; i<cnt; i++)
	{
		sleep(1); puts("running thread");
	}
	return NULL;
}

  • 프로세스 종료되면 쓰레드도 종료됨. 그거 막기 위해 sleep(10)
  • thread_param을 주소 값으로 전달하면 쓰레드에서 int 포인터로 변환
  • 책과 다르게 컴파일 시 -lpthread 옵션 추가 안 했는데, 멀쩡히 작동됨. Ubuntu같은 배포판은 gcc가 자동 포함하도록 설정돼있다고 함

지금처럼 쓰레드 끝날 때까지 sleep()하는 건 비현실적
pthread_join() : 인자로 전달된 쓰레드가 종료될 때까지, 해당 함수 호출한 프로세스(또는 쓰레드) 대기상태에 둔다.

	if(pthread_create(&t_id, NULL, thread_main, (void*)&thread_param)!=0)
	{
		puts("pthread_create() error");
		return -1;
	};

	if(pthread_join(t_id, &thr_ret)!=0)
	{
		puts("pthread_join() error");
		return -1;
	};

	printf("Thread return message: %s \n", (char*)thr_ret);

임계영역 내 호출 가능 함수

임계 영역 : 둘 이상의 쓰레드가 동시에 실행하면 문제 일어나는 문장 존재하는 함수

쓰레드 안전 함수

  • 동시 호출 및 실행돼도 문제 안 일어나는 함수
  • 임계영역 있어도 적절한 조치 취하면 쓰레드 안전해진다.
  • 대부분의 표준함수는 쓰레드 안전하다
    • 안전하지 않은 함수 있어도 그에 대응되는 쓰레드 안전 함수가 있다
    • 리눅스에서 쓰레드 안전한 형태로 재구현된 함수에는 _r이 붙는다
    • 현대 리눅스는 대부분 아예 다른 대체 API 제공하거나 쓰레드 안전하게 바꿔놓음

워커(Worker) 쓰레드 모델

1부터 10까지의 덧셈 결과를 출력하는 프로그램 만들 때,
쓰레드 두 개가 각각 1~5, 6~10 연산하면 이것을 Worker thread 모델이라 함.

long long num = 0;

int main(int argc, char *argv[])
{
	pthread_t thread_id[NUM_THREAD];
	int i;

	printf("sizeof long long: %d \n", sizeof(long long));
	for(i=0; i<NUM_THREAD; i++)
	{
		if(i%2)
			pthread_create(&(thread_id[i]), NULL, thread_inc, NULL);
		else
			pthread_create(&(thread_id[i]),NULL, thread_des, NULL);
	}

	for(i=0; i<NUM_THREAD; i++)
		pthread_join(thread_id[i], NULL);

	printf("result: %lld \n", num);
	return 0;
}

void * thread_inc(void * arg)
{
	int i;
	for(i=0; i<5000000; i++)
		num+=1;
	return NULL;
}
void * thread_des(void * arg)
{
	int i;
	for(i=0; i<5000000; i++)
		num-=1;
	return NULL;
}

두 쓰레드가 하나의 전역변수 num에 여러 번 접근하기 때문에, 오류 발생



profile
너 정말 **핵심**을 찔렀어

0개의 댓글