주로 멀티 스레드를 배울 때 자주 나오는 용어. 멀티 스레딩은 프로그램의 동시성을 구현하는 방법이다.
동시성이란 두 개 이상의 단위 작업을 동시에 처리하는 것을 의미한다. 그런데 이 동시에 처리한다는 말이 좀 애매모호해서 오해가 발생한다.
두 작업이 동시에 처리된다? 그렇다면 두 프로세서에서 두 작업을 각각 처리하는 건가? 정답은 아니다.
여러 프로세서에서 여러 작업을 처리하는 건 병렬성
이 성립하는지 여부이고, 동시성은 작업이 아닌 cpu를 주체
로 놓고 봐야 한다.
행간을 읽자면 cpu 하나당 동시에 n개 이상의 여러 작업을 처리하는 방식
이 동시성이라고 볼 수 있다.
목적 관점에서 보자. 동시성은 크게 두 가지 목적을 가진다.
P1,P2 두 프로세스가 현재 돌고 있고, CPU 코어는 하나라고 가정해보자.
P1이 디스크 r/w IO 작업 시스템 콜을 보내게 되면, P1은 자동으로 wait queue로 빠지게 된다. 이 때 OS는 어떤 선택을 해야 할까? IO 작업을 blocking으로 두면 P2는 CPU에서 처리 가능함에도 불구하고, CPU를 점유할 수 없게 된다. 이 때 OS에서 센스 있게 P2로 컨텍스트 스위칭을 해주면, P1이 IO 작업 결과를 대기하는 동안 CPU는 P2를 처리할 수 있게 된다. 따라서, CPU 사용률이 올라 간다.
이 관점에서 동시성은 정해진 타임라인 위에서 P1과 P2를 효율적으로 배분하여 CPU 사용률을 높이기 위해 프로세서가 동시에 여러 작업을 바꿔가며 진행하는 것을 뜻한다.
p1...,pn까지 n개의 프로세스가 있고 CPU 코어는 하나라고 가정해보자.
이제 p1에서 pn까지 순차적으로 처리된다고 가정해보자. 그러면 p1이 끝나야 p2 작업이 수행 될 수 있고, pn은 앞의 모든 프로세스가 수행될 때까지 대기해야 한다. 자, 이제 pn이 키보드 타입 결과를 받아 velog 블로그 글을 업데이트 해주는 프로세스라고 하자. 그런데 모든 프로세스가 순차적(sequential)하게 처리된다면, 내가 지금 타이핑 하고 있는 문자가 굉장한 딜레이를 가지고 반영이 될 것이다.
이런 문제를 해결하기 위해 OS는 time-division multiplexing, 즉 특정 주기를 가지고 각 프로세스들을 interweaving해서 처리하게 된다. 최초 가정이었던 프로세서가 하나인 모델을 생각해보면, 이 프로세서가 p1...pn까지 OS 스케쥴러 알고리즘에 따라 왔다 갔다 하면서 동시에 여러 프로세스를 바꿔가며 처리 하게 된다.
이 스케쥴러 알고리즘에 우선순위를 둬서, 내가 velog에 타이핑 하고 있는 프로세스에 우선권이 부여된다면, 다른 백그라운드 프로세스가 돌고 있더라도 타이핑 하는 순간 OS가 타이핑을 반영하는 프로세스를 우선적으로 처리 해서, 사용자에 대한 프로그램의 반응성이 좋아지게 된다. 물론, 이 사용성은 컨텍스트 스위칭 비용을 댓가로 지불 하게 된다(thrashing) .
두 예시 다 cpu 하나가 동시에 여러 프로세스를 왔다 갔다 하면서 처리한다는 공통점을 가지고 있다. 즉, 동시성
은 cpu와 프로세스 사이에서 1:n 관계가 있어 이걸 어떻게 전환하며 처리하는지, CS 관점에서 작업 단위의 교차실행
대한 것이고, 병렬성
은 여러 프로세스(혹은 스레드, 혹은 더 넓은 범위의 작업들)가 같은 타임 t0에 동시에 처리 되는지, 물리적 의미에서 동시실행
여부에 대한 것이다.
이건 어떻게 보면 교차실행
에 필연적으로 따라오게 되는 문제라고 볼 수 있다.
스레드 t1,t2가 있다고 가정하자.
여기서 두 가지 염두해 둬야 할 게 있다.
OS의 스케쥴링으로 인해 t1,t2의 코드는 여러 경우의 수로 interweaving 된다. 그리고 각 경우의 수 마다 t1의 실행코드와 t2의 실행코드가 막 뒤섞이게 되는데, 이 때 공유자원에 접근하는 코드들의 순서가 섞이게 되면 당연히 접근 순서에 따라 결과가 바뀌게 된다.