[sw정글-북] 📚CSAPP 12장-Concurrent Programming
카테고리: swjungle CSAPP
📚📚CSAPP 12장-Concurrent Programming
🚀노션에서 업데이트 된 최신 내용으로 보기
📚CSAPP 12장 <== 클릭
📚CSAPP 12장 <== 클릭
📚CSAPP 12장 <== 클릭
❗️출처: 하이애나 블로그
📕start
- 12장 동시성
- 느린 IO디바이스 접근하기
- 사람들과 상호작용
- 작업 지연시켜서 시간지연을 줄이기(coalscing같은거 나중에 백에서 하기)
- 다수의 네트워크 클라이언트 처리
- 멀티코어 머신에서 병렬로 계산하기
- 프로세스
- I/O다중화
- 쓰레드(12장 뒷부분, 쓰레드를 병렬로 처리하는 법)
- 12.1 프로세스를 사용한 concurrent programing
-
(1단계)
- 부모와 자식 관계임
-
(2, 3단계)
- 부모가 연결식별자의 자신만의 사본을 닫는 것은 매우 중요하다
- 포크뜨고 내꺼 닫는다(connection descriptor 여러개면 연결이 여러개 되니까)
-
(4단계)
- 1,2,3,4단계 완료!!
-
서버들은 대개 장시간 돌아가니까 SIGCHILD 핸들러로 따로 관리를해야함
- 포크를 뜬 녀석(자식)들은 SIGCHILD 핸들러 관리대상으로 들어가게 됨
-
- 12.1.2 프로세스의 장단점
- 프로세스가 많아지는게 장점이자 단점임
- 문제생기면 단일프로세스 처리해주면 되지만, 다른 프로세스들이 죽어있는지 살아있는지 알 수 없다.
- 그러니까 IPC를 만들어서 서로 상태를 공유하자!! 그런데 IPC때문에 조금 느려짐
- 12.2 I/O다중화를 이용한 동시성 프로그래밍
- 여러 I/O디바이스가 있으면 동시에 들어온 신호들을 한번에 처리해줄 수 없음
-
프로세스는 여러개 프로세스를 쭉 만듬, 하지만 이거는 하나의 프로세스에서 처리해줌
- 프로세스 안에, 각자 I/O디바이스에 대한 상태머신이 있음
- 어려움… (성훈형: 나중에 좀더… 보자…)
- 12.2.2 I/O다중화의 장단점
- 데이터공유가 쉬움
- 코딩복잡도가 높아짐
- 12.3 쓰레드를 이용한 동시성 프로그래밍
- 프로세스 안에서 동작하는거
- 단일쓰레드, 다중쓰레드가 있음
- 공유하는 자원이 있고, 별도의 자원이 있음
- 프로세스경우에는 각자의 개별자원을 들고있지만, 쓰레드같은경우에는 공유하는 자원도있고 별도의 자원이 있다는 뜨싱ㅁ
- 스택이랑 PC는 별도로 쓰고,
- 힙, 라이브러리코드, 데이터영역 등은 같이 공유함
- 프로세스 하나로 돌릴거를, 쓰레드 써서 여러개에서 돌릴수 있다!! 이런 개념임
- 12.3.1 쓰레드 실행 모델
- 메인쓰레드 하나 만들고, 개가 동료 쓰레드를 만듬
-
아까는 부모자식 관계였지만, 여기서는 동료(peer) 쓰레드를 만듬
- 자신의 피어를 모두 죽이거나, 자신의 피어들이 종료하는것을 기다릴 수 있음
- 피어는 동일한 고유데이터(위에서 말했던, 힙, 라이브러리 등)를 읽고 쓸 수 있다
- 피어에서도 메인 종료 가능, 메인에서도 피어 종료 가능
- 12.3.2 Posix 쓰레드
- POSIX는 IEEE가 제정한 유닉스의 애플리케이션 프로그래밍 인터페이스 (API) 규격
- Posix쓰레드는C프로그램에서쓰레드를조작하는표준인터페이스다
- 프로세스 안에서 동작하는거
- 12.4 쓰레드 프로그램에서 공유 변수
- 12.4.1 쓰레드 메모리 모델
- 12.4.2 변수들은 메모리로 매핑하기
- 전역변수는 당연히 공유가 가능할테고,
- 12.4.3 공유 변수
- 공유를 보여주는 프로그래밍
- 위 그림에서 ptr과 msg.m만 공유변수임
- ptr[myid] ← 공유변수임 메인함수에서도 쓰이고 다른데서도 쓰인다 어쩐다 함
- 12.5 세마 포어로 쓰레드 동기화하기
- A, B, C 가 쓰레드 중
- 한 변수를 여러 쓰레드에서 동시에 써버리면 혼란스러움
- 한 변수는 한 쓰레드에서만 돌아가고 있어야 함
- 다익스트라가 세마포어 개념을 만듬
- 쓰레드 코드설명
H,L,U,S 순서대로 움직여야함, 하지만 (b)에서는 HLUH 로, H가 침범해버림…ㄷ
-
그래서!! 세마포어!!
- 그래프에서 HLU하다가 갑자기 Unsafe region에 들어가버림
-
critical region(=unsafe region)
- A, B, C 가 쓰레드 중
- 12.5.2 세마포어의 핵심
-
P, V(중요중요중요중요함)
- P(s)
- 0이 아니면 S감소
- 0이면, V가 시작될 때 까지 기다림
- V(s)
- P 깨워줌, S를 1 증가시킴
- 화장실칸 비어있으면 1, 아니면 0, 그리고 새로운 P가 왔는데 자리가 없으면 기다림(자고있음)…. 화장실 한칸 다쓰고 나옴(화장실 쓰고 나오는게 V임)
- 그래서 화장실(s)는 0,1,0,1,0,1만 반복됨. 모든 화장실(s)가 꽉차있으면 새로운 프로세스는 잠자는거임(기다림), 똥 다싸면 깨워줌
- 세마포어 불변성:
- 0, 1의 값밖에 가질 수 밖에 없다
- unsafe region은 그래서 -1임, s가 -1이 되면 침범당한거임
- 세마포어의 기본 모양
-
- 12.5.4 세마포어를 이용한 공유자원 스케줄링
- 화장실의 세면대의 경우 1개이지만 여러명이 공유해야함
- 이때 세마포어 개념이 또 들어갈 수 있음
- 생산자- 소비자 문제
- 비디오 인코딩 디코딩
- 비디오를 인코딩해서 버퍼에 냅두면, 소비자가 그 인코딩된거를 들고 나갈 수 있음
-
이것도 세마포어로 풀 수 있음(세마포 3개)
- 붕어빵 비유
-
붕어빵 틀이 필요
-
공유자원(팥 밀가루 물 쓸거야)
-
팥 밀가루 쓰는거
-
붕어빵 다 만들고나면, 버퍼에 붕어빵 쌓아둠, 그럼 소비자가 또 가져감
- 생산할때도 semaphore개념이 들어가고, 소비할 때도 semaphore개념이 들어감
-
- 읽기-쓰기 문제
- reader는 많을 수 있되, writer는 딱 한명만 할 수 있게
- 티켓팅임
-
reader를 먼저 할껀가, writer를 먼저할것인가
- writer코드는 엄청 간단함
- 한명이 쓰고있으면 다른사람들은 아무것도 하지 못함
- reader 코드
- 첫번 째 들어간 사람만 편집할 수 있음
- 두번째, 세번째 들어간 사람은 읽기만 가능
- 12.6 병렬성을 위해서 쓰레드 이용하기(Using Threads for Parallelism)
- 요즘 멀티코어에서 동시성프로그램 돌리면 훠~얼씬 더 빠름
- OS 커널이 멀티코어에 병렬로 스케줄 하기 때문
- 그렇기에 DB, 실험, 웹서버 등에서 중요
- 순차적프로그래밍
- 단일 논리흐름으로 작성 가능
- 동시성 프로그램
- 다수의 동시성 흐름
- 병렬프로그램 ⇒ 멀티프로세서에서 돌아가는 동시성 프로그램
- (그래서 위에 그림보면, concurrent 속에 parallel있음)
- 1,2,3,4,5….999 까지 더하려면…??
-
1)
- 쓰레드 ID로 사용되는 정수를 각 피어쓰레드로 전달
-
2)
- 한개의 공유전역변수에 그 합을 저장함
-
-
그런데…쓰레드 늘어나면 더 느려짐
- P, V 동기화연산이 메모리 갱신할 때보다 매우 비쌈
- (TBD 이해 잘 안감) 동기화 오버헤드는 비싸고, 가능하면 피해야 함
- 오버헤드는 유용한만큼만 넣어야 함
- 정리
- (같이쓰는)공유전역변수에 그 값을 넣으려면 P, V 계산 코스트가 비싸다
- 그러니까 그냥 psum을 따로 정의하고 자기꺼 돌리고 돌려주면 됨
- Psum[core1, core2, core3, core4] 만들고 Psum[] 다 더해버리면 끝
- 병렬 프로그램 성능의 특성분석
- 네개의 코어가 최소 1개의 쓰레드를 바쁘게 돌리는 지점까지는 good
- 그 이상의 쓰레드는 오히려 느려짐
-
따라서… 이를 위한 계산식
- p: 프로세서 코어수, k: 코어에서의 실행 시간
- 강한 스케일링
- 문제는 그대로, 컴퓨터만 키움
- ⇒ 얼마나 좋아졌는지?
- 문제는 그대로, 컴퓨터만 키움
- 약한 스케일링
- 문제도 키우고, 컴퓨터도 키움
- ⇒ 얼마나 좋아졌는지?
- 문제도 키우고, 컴퓨터도 키움
- 12.7 다른 동시성 이슈(Other Concurrency Issues)
- 공유데이터의 접근을 동기화 ⇒ 인생이 힘들어지는 코딩 해야함
- 다음과같은 5가지 이슈들
- 쓰레드 안정성, 재진입성, 라이브러리사용, 경쟁, 교착
- 12.7.1 쓰레드 안정성
- 항상 정확한 결과만 리턴해야함
- 쓰레드-안전 ↔ 쓰레드-위험
- 쓰레드 위험 함수들
- 1번CLASS:공유변수를 보호하지 않는 함수
- (P, V 동기화시켜서 안전하게 보호해야함)
- 2번CLASS: 다중호출에 대해 상태를 유지하는 함수
- random 생성 함수
- seed값 가져와서 해당 반복되는 해당 배열을 호출해야함
- 하지만 다수의 쓰레드가 rand를 호출하면…?
- static 데이터를 전혀 사용하지 않도록 하는 것
- 호출자가 상태정보를 인자들로 전달해야함
- 씨드규칙1로 잘 하고있었는데…. 씨드규칙2로 바뀌어버림
- 다른 쓰레드에서도 씨드규칙 2로 하게되면 두 쓰레드가 같은 규칙을 가지게 되므로 문제가 발생
- random 생성 함수
- 3번CLASS: 정적 변수를 가리키는 포인터를 리턴하는 함수
- ctime(현재시간 알아오는 함수), gethostvyname
- static변수가 가리키는 포인터를 리턴하는 함수임
- A쓰레드가 B쓰레드를 덮어버릴 수 있음
- static영역, 즉 data 영역에 있는값을 바꿔버려서 나중에 시간 물어봤는데 이상한 소리할 수 있음
- 해당영역 포인터값이 바뀌었기 때문에 어쩔 수 없음)….
- ctime(현재시간 알아오는 함수), gethostvyname
- 4번CLASS: 쓰레드 위험 함수를 호출하는 함수(당연한 소리…)
- 1번클래스, 3번클래스 경우
- 1번CLASS:공유변수를 보호하지 않는 함수
- 12.7.2 재진입성
- 위의 2번함수를 쓰레드 안전으로 만드려면, 함수를 작성해서 재진입가능하게 하는 법밖에…
- 로컬만 쓰는애들이 재진입성을 가지고 있는 애들임, 스태틱같은거 쓰면 재진입성이 떨어진다?
-
위험한 함수예시(rand 결과값이 같아져버림)
- 묵시적: A랑 B랑 같은 경로를 교대로 번갈아가면서 뱉아줌
- 명시적: 아싸리 다른 경로를 그림
- 12.7.3 쓰레드 프로그램에서 기존 라이브러리 함수 사용
-
위험한 함수 있지만 안전한 버전이 있다…
- ctime을 쓰려면 lock-and-copy를 써야함
- 하지만… lock and copy쓰려면 힘듬, 느려지고, 구조체도 복잡해짐
- 그래서 (함수) + (_r)쓰면 됨
- 이거 그냥 무조건 좋음
- 가능한 무조건 Linux thread-safe version쓰면 됨
-
- 12.7.4 경쟁상태(Race condition)
- atomic 써서 그사이에 어떤일도 일어나지 않도록 함
- 똥칸 표시를 아주 재빠르게 해준는거임
-
12.7.5 교착상태(Dead lock)
- 교착상태 : 두 쓰레드가 서로 필요한 자원을 점유한 상태에서 기다리느라 지원이 멈춰지는 상황
-
교착상태(사진)
-
교착상태 해결(사진)
-
- 교착상태 : 두 쓰레드가 서로 필요한 자원을 점유한 상태에서 기다리느라 지원이 멈춰지는 상황
- 12.8 요약
- skip
- 추가내용
- Static? Heap? 메모리?
- 초기화하지 않으면 애초에 메모리에 안올림
- 파일 불러오면 static 선언된거 다 쓸 수 있음
- static은 데이터 영역에 새겨짐
- gloabal도 데이터 영역에 새겨짐
- 데이터
- bss 초기화되지 않은 전역, 정적
- .data는 초기화된 전역,정적
- 스택
- 지역변수, 매개변수
- 힙
- 필요한 메모리의 크기를 프로그램이 실행되는 동안 결정해야 할 때
- Static? Heap? 메모리?
🚀노션에서 업데이트 된 최신 내용으로 보기
📚CSAPP 12장 <== 클릭
😵배우면서 깨달은 내용을 정리해 보았습니다. 틀린 것 같은 개념을 아래 댓글에 달아주시면 감사합니다😵
🌜 Thank you for reading it. Please leave your comments below😄
댓글 남기기