프로그램 => 파일이 저장 장치에 저장되어 있지만 메모리에는 올라가 있지 않는 정적인 상태
프로세스 => exe파일을 실행했을 때 프로그램은 컴퓨터 메모리에 올라가게 되고, 이 상태를 프로세스라 한다. 즉 실행되고 있는 컴퓨터 프로그램
이라 생각하면 된다.
스레드 => 프로세스와는 다른 더 작은 실행 단위 개념
이다. 즉 프로세스와 다르게 스레드간 메모리를 공유하며 작동한다. 스레드끼리 자원을 공유하며 실행하게 된다.
프로세스들이 메모리에 올라갈 때 운영체제로부터 시스템 자원을 할당받는다.
이 때 각각 독립된 메모리 영역을 Code/Data/Stack/Heap
의 형식으로 할당한다.
각각 독립된 메모리 영역을 할당
하기 때문에 프로세스들은 각각 다른 프로세스의 변수나 자료
에 접근할 수 없다.
프로세스가 할당받은 메모리 영역 내에서 Stack 형식으로 할당된 메모리 영역
을 따로 할당받고 나머지 Code,data,heap
메모리 영역을 공유한다.
따라서 각각 스레드는 별도의 stack
을 가지고 있지만 heap
메모리는 서로 읽고 쓸 수 있다.
프로세스를 실행하다가 오류가 발생해서 프로세스가 강제로 종료된다면, 다른 프로세스에게 어떤 영향을 주지 않는다. 왜냐하면 서로 다른 메모리 영역을 공유하기 때문이다.
반면에 스레드 내 오류가 발생한다면 모든 작업을 중단하고 프로세스를 끝내버린다.
멀티 태스킹이란 하나의 운영체제 안에서 여러 프로세스가 실행되는 것을 의미한다.
실행될 때 동시에 실행되는 것이 아니라 스케쥴러를 통해 실행된다.
반면에 멀티 스레드는 하나의 프로세스가 여러 작업을 여러 스레드를 사용하여 동시에 처리하는 것을 의미한다.
멀티스레드는 아무래도 긴 작업이 걸리는 스레드가 진행되는 동안 다른 스레드에서 사용자와 상호작용할 수 있고, 자원들을 공유하기 때문에 경제적으로 사용할 수 있다.
멀티스레드에서는 동기화 문제를 생각해야 한다.
어떠한 자원을 수정했을 때, 바뀐 자원에 대한 오류가 발생할 수 있다.
경생상태 => 둘 이상의 쓰레드가 공유자원을 병행적으로 읽거나 동작할 때 타이밍이나 접근 순서에 따라 실행 결과가 달라지는 상황
해결하는 방법
원자성 => 공유 자원에 대해 작업의 단위가 더 이상 쪼갤 수 없는 하나의 연산인 것처럼 동작하는 것
가시성 => volatitle, 메인 메모리에서만 값을 읽고 cpu 캐시를 사용하지 않는다.
synchronized 동작방식 => 한 스레드가 임계구역에 들어와서 계산 후 메인 메모리에 반영시킨 후 임계구역에 나간다. 그 후 기달리고 있는 다른 스레드가 이미 동기화된 값을 읽어오기 때문에 원자성과 가시성을 보장해준다.
=> 이렇게 하면 나머지 스레드는 대기해야 하고 데드락이 발생할 수 있다.
데드락은 자기가 잡고 있는 자원을 놓지 않고 상대방이 자원을 놓기를 기다리느 상태를 데드락이라 한다.
논블로킹 => 다른 스레드의 작업여부와 상관없이 자신의 작업을 수행하는 방식
Atomic 타입
여기서 Volatitle와 CAS알고리즘이 사용된다.
Volatitle은 메인 메모리를 바로 참조를 한다.
그래서 메인메모리에 저장된 값과 CPU 캐시에 저장된 값과 다른 경우가 발생할 수 있다. 이럴 때 비교해주는 알고리즘이 CAS알고리즘이다.
현재 스레드에 저장된 값과 메인 메모리에 저장된 값을 비교하여 일치하는 경우 새로운 값으로 교체되고, 일치하지 않는다면 실패하고 재시도를 한다.
스레드 안전한 객체를 설계하는 법 => 공유변수 최소화 + 아니면 캡슐화로 한곳에 모아두거나, 문서화 잘하는 것이 중요하다.
양방향 통신
통상적인 HTTP 통신은 client 요청에만 server가 단방향으로 통신한다.
클라이언트 서버가 원할 때 데이터를 주고받을 수 있따.
io.on("connection", (socket) => {
socket.on("chatting", (data) => {
const {name, msg} = data;
io.emit("chatting", {
name,
msg,
time : moment(new Date()).format("h:ss A")
});
})
})
connection 이벤트는 클라이언트가 처음 접속했을 때 발생한다.
그리고 클라이언트에서 chatting이라는 이벤트명으로 데이터를 보낼 때 서버에서 받는 함수이다.
emit을 통해서 클라이언트들에게 메시지를 전송한다.
socket.on("chatting", (data) => {
const { name, msg, time} = data;
const item = new LiModel(name, msg, time);
item.makeLi();
displayContainer.scrollTo(0, displayContainer.scrollHeight);
})
클라이언트에서 chatting이라는 이벤트명으로 데이터를 받는 함수이다.