- 호출 스택 : 함수는 자신의 함수 영역을 다 실행 한 뒤 자기 자신을 호출 했던 호출자함수를 실행했던 지점으로 돌아간다 이렇게하려면 어디까지 실행하다 말았는지 기억하고 있어야하는데 이 '어디까지 실행하다 말았는지'정보를 가지고 있는 곳을 호출 스택이라고 한다.
프로스세스(실행 중인 프로그램)이 실행 된다면 그 후에 메인 스레드(프로세스 내의 실행 단위)가 생성되고 여러가지 스레드들이 실행 될 수 있다 한 프로세스 내의 스레드들은 프로세스으 자원을 공유하면서 각자의 스택영역을 가지게 되면서 자신의 역할을 마무리하면 사라진다.
- .join함수가 메인 스레드는 끝났더라도 서브 스레드가 끝가기를 기다려주는 함수이다 그러나 이전에 서브 스레드가 끝이 났다면 .join을 보고 지나치면서 함수 실행을 끝낸다..
스레드 프로그래밍은 언제?
스레드
- 스레드는 왔다갔다하면서 일을 하게된다 이럴때 스레드가 스레드1에서 스레드2로 가면 컨텍스트 스위치가 발생하게된다. 컨텍스트 스위치를 하게된다면 호출스택을 저장하고, 과거에 실행하다가 만 다른 스레드 중에서 하다를 고르고 그것의 호출 스택을 복원하고 실행 지점으로 이동해야한다 . => 이렇게 연산이 많아서 할일이 많아진다
- 비둘기 집을 예로 들었을 때 비둘기 집은 CPU이고 비둘기들은 스레드들이다.
스레드 주의사항
- 밑의 그림에서 여러 스레가 동시에 num을 건드려서 값의 변경이 제대로 안이루어 질 수도 있습니다.
- 이 때문에 같은 값을 두번 연산하거나 연산을 뛰어넘거나 합니다.
- 하나의 스레드가 건드리는 동안 다른 스레드는 건드리지 못하도록 막아야한다, 이를 원자성이라하고 두 변수끼리는 항상 일관성 있는 상태를 유지해야해서 일관성이라고한다.
- 이러한 것들을 위한 기법으로 동기화, 임계 영역, 뮤텍스(상호배제), 락기법이 있다
스레딩 mutex 기법 (cpp)
#include <bits/stdc++.h>
#include <mutex>
using namespace std;
void read();
void write();
void sum();
int main() {
mutex mx;
lock_guard<mutex > lock(mx);
read(x);
write(x);
sum(x);
return 0;
}
- 위의 소스처럼 locak_guard를 이용해서 락을 할 뮤텍스 변수를 lock 안에 걸어두고 끝나면 자동으로 unlock하도록한다.
스레드 풀링
- 멀티스레딩을 할 때 스레드는 몇개를 만들 것인가?, 무엇을 위해서 일을 할 것인가?
- 게임에서 볼때 클라이언트 수에 따라서 각 스레드를 할당 시킨다? 안된다 부하가 엄청나다 왜냐 컨텍스트 스위치를 생각해야하기 때문에... 그러면 생각하는 방식이 스레드 풀링이다 그게 머냐?
- 스레드 풀링 , 각문은 스레드이고 문의 집합은 화장실은 스레드 풀입니다. 이렇게 하면 많은 수의 스레드를 동시에 처리가능하고, 너무 많은 스레드를 두었을 때 발생하는 문제점을 방지할 수 있다.
- 성능(속도)향샹 왜? 미리 만들어 놓은 쓰레드들을 필요할 때마다 꺼내서 쓰고, 소멸을 시키지 않고 풀에 반납을 한다.
- 커널 개체들은 생성과 소멸에 대해서 비용이 많이들어간다.. 그래서 쓰레드 풀을 이용하면 여러 이점이 존재한다.
- 만약 cpu가 8코어이고 스레드가 6개이면 ? -> 그냥 덜 사용하는 것이다. 6 / 8만 cpu를 사요하는 것이라서 안된다.
- 그럼 cpu가 8코어이고 스레드가 10개가 준비되어 있다면 2개는 어디가서 대기를 해야한다...
- 스레드 수를 결정하는 것은 고민이다
- 파일 엑세스나 다른 컴퓨터에서 결과를 수신하는 결과를 수행하면 스레드가 잠자는 디바이스 타임이 있을 수도 있다.
- 이럴 때는 스레드수가 cpu개수보다 많아도 된다, 그러나 일반 연산 할때는 cpu개수랑 스레드 풀의 스레드 개수는 동일해야한다.
원자 조작
- 원자조작은 뮤텍스나, 임계 영역의 잠금 없이도 스레드가 안전하게 접근 되는 것을 말한다.
멀티스레드 프로그래밍의 실수를 방지하다.
- 읽기와 쓰기 모두에 잠금을 하자!
- 메모리에 값을 쓰고 있을 때 다른 스레드가 그것을 접근하면 안되는 것을 알긴 하지만, 단순히 읽기만 하면 상관없지않나라고 생각에 발생한다 -> 그러나 값을 읽을 때 한번씩 이상한 버그가 발생 할 수도 있습니다(값이 변경되고 있으니,,,).
- 잠금 순서를 꼬지말자
- 잠금된 뮤텍스나 임계 영역을 삭제하지 말자
- 이 경우는 delete 함수 안에 이미 잠금하고 있으면 오류를 내는 기능을 추가하면된다.