프로세스를 생성하는 건 자원과 시간이 많이 든다.
그런데, 이러한 프로세스를 만들어서 같은 자원으로 같은 일을 하게끔 시키면 비 효율적
ex) 레지스터도 계속 바뀌어야 하고,, 데이터도 계속 바뀌어야 하고,,
heap을 쓰레드 마다 sub dividing 하긴 해요.
응답성
gui 등등,,
자원 공유 : 같은 주소 공간 내의 자원에서 다른 흐름
경제성 : 프로세스의 자원을 공유함에 따름. 문맥 교환과 프로세스 생성에 효율적(메모리, 시간)
유저레벨 쓰레드라면 확실히 문맥교환이 빠르다.
scalability : 다중 처리기에서,
다중 처리기 이전에는, 병행성을 빠르게 해서 병렬성의 환상을 심어줌.
다중 처리기는 실제로 병렬성을 보여준다.
암달의 법칙
순차 실행이 많다면, 코어를 많이 만들어도 성능 향상을 많이 얻을 수 없다
테스크 병렬실행
웹 브라우저 처럼, 각각의 데이터를 적당히 쓰는 것
데이터 병렬실행
마치 딥러닝 처럼 쫙 나누는 느낌
어차피 둘 다 쓰게 된다.
현재 진행중인 쓰레드에 대한 레지스터와 TCB, stack등을 저장하고
레디큐에서 새로 진행할 쓰레드를 뺸 다음에
새로 진행할 쓰레드의 그런거를 processor에 적재한다.
쓰레드 진행 시 TCB POITNER를 이용해서 현재 TCB를 가리키게끔 행동하게 한다.
유저레벨에서의 premption은 upcall을 통해 구현 가능하다.
user process의 라이브러리로 실행
스케줄링, context switching, create, destory, thread끼리의 통신 등등 모두 다 지들이 알아서 할 수 밖에 없네,,
빠르다
I/O 등에 의한 block시 전체가 block
시스템 콜 할 때 리턴 값으로 어떤 thread한테 반환해야 하는 지도 잘 모른다.
병렬 실행이 불가능하다.
즉, 다중 코어 좆까라이다.
유닉스 : 사용자, 커널 모두 가능한 쓰레드 라이브러리
윈도우 : 커널 수준 라이브러리
비동기 스레딩 : 안 기다리고 다른 일
동기 스레딩 : 딱딱 타이밍 맞춰서.
여담
fork 하면, 다른 쓰레드 들은 모두 죽어버린다.
exec하면, 아예 새로 써버리기 때문에 상관 없지만,
그 전에는 메모리 누수 등의 심각한 문제들이 발생 가능,
심지어, 다른 쓰레드에서 어떤 공유변수에 접근한 상태였다면, mutex lock같은 자원을 들고 죽어버리게 된다.
상황에 따라 다를 수도 있다.
윈도우도 그냥 비슷하구나..
jvm - 내부에서
일단 두가지 스레드 방식
runnable class
executor class
운체와 컴파일러가 알아서 해쥬,,ㅚ
무한히 스레드를 만들 순 없으니, 양을 정하자
장점
적절한 양 제한
애초에 스레드를 만들어 두는게 더 빠르다
안드로이드 서비스는 일단 스레드 풀을 열어놓고 합니다.
백그라운드에서 스레드풀을 열어 놓고, 배분해주는 방식
서비스가 RPC로 이루어져 있다는 것은.. 알겠죠?
이전의 스레드 라이브러리 같은 느낌
만들고, 이를 기다리기
진짜 fork join을 말하는 것은 아닙니다.
디폴트 signal handler가 있구여, 프로그램마다 signal handler를 정할 수 있어요.
쓰레드를 위한 kill이 있다.
pthread_kill(pthread_t tid, int signal)
윈도우는 비동기식 프로시저 호출을 한다. 그냥 어떤 이벤트에 어떤 함수를 실행할 건지 어플리케이션에서 해놓고, 커널에서 프로시저 호출을 함
만약, 어떤 쿼리를 막 100개의 스레드가 찾았는데, 하나가 찾았어, 그러면 다른 애들은 다 꺼야지
문제점(어려운 점)
취소 스레드에게 할당된 자원 문제
작업 중 취소되는 문제
지연취소는 물론 좀 덜함
pthread_testcancel() : 자식 스레드가, 혹시 밖에서 취소요청 들어왔는지 확인하는 일.
정리핸들러를 돌려서 thread가 얻어 놓은 자원을 다 뱉어놓는다.
사용자 스레드와 커널 스레드의 중간
LWP는 커널 스레드 하나를 받는다.
스케줄링은 커널 스레드마다 실행된다.
사용자 스레드 입장에서는, 마치 프로세서 처럼 보인다.
가용한 커널 스레드 풀(LWPS)을 가지고, 유저 프로세스에게 upcall을 때린다.
upcall 자체도 일단 커널스레드에서 실행한다.
그러면, 유저 프로세스의 스레드 라이브러리의 upcall 프로시저를 커널 스레드에서 실행한다.
이런 방식으로, 몇 개의 커널 스레드들을 주고 알아서 스케쥴링 하게끔 한다.
블록이 된 상황에서, 커널 스레드가 결국 실행하므로 업콜을 때려서, 스레드 라이브러리에서 스케줄링을 하게 해준다. 스레드 라이브러리에서 스케줄링 하기 위해 새로운 LWP를 발행해준다. 그러면, 해당 스레드 라이브러리에서 막 콘택스트 스위칭 같은 거르 한다.
블록이 풀리는 상황에는, 다시 커널에서 유저 스레드 라이브러리로 업콜을 때려주고, LWP 받아서 핸들러 실행하고, 새로운 LWP 받아가지고 실행하려는 스레드에 붙여주고,, 한다.