동기화와 락( Lock )의 종류에 대해
동기화란?
앞의 글에서 멀티 스레드를 사용할 때, 스레드는 stack영역만 독자적으로 할당받고 나머지 메모리 영역은 공유를 한다고 하였다. 그럼 heap, data영역에 있는 값에 여러 스레드가 동시에 접근을 하게 되면 어떻게 될까?
당연하게 문제가 생기는데 읽기와 쓰기가 동시에 일어날 수도 있기 때문에 원하는 대로 값들이 나오지 않고, 메모리 해제와 동시에 해당 메모리 영역을 가리키게 되면 프로그램이 crash날 가능성도 있다.
이러한 문제를 해결하기 위한 것이 동기화이다.
즉 멀티 스레드 환경에서 여러 스레드들이 같은 메모리주소나 값에 접근을 할 때, 서로 작업한 내용들을 일치시키는 것을 동기화라고 한다.
임계 영역( Critical Section )이란?
임계 영역이란 위에서 말한 여러 스레드들이 동시에 접근을 했을 때 문제가 생길 수 있는 부분을 처리하기 위해 한번에 하나의 스레드만 해당 영역에 접근이 가능한 곳을 뜻한다.
이 임계 영역부분을 통해서 스레드 동기화 문제를 해결할 수 있기 때문에, 이 접근 권한을 주는 것이 매우 중요하다.
락( Lock )이란?
이 임계 영역에 접근할 수 있는 권한을 뜻한다.
이 락을 가지고 있는 스레드만 해당 임계 영역에 접근을 가능하도록 하여 임계 영역에 대한 독자적인 권한을 주는 동기화 방식이다.
락은 크게 두가지로 나눌 수 있는데, 유저 모드 동기화와 커널 오브젝트 동기화이다.
유저 모드 동기화로는 critical section과 Interlock등이 존재한다.
커널 오브젝트 동기화로는 뮤텍스, 세마포어, 이벤트 등이 있다.
critical section : 윈도우에서 지원하는 동기화 기법중 하나. critical section 생성 -> 권한 획득 -> 권한 반납 -> 제거로 이어짐
interlock : 윈도우에서 지원하는 동기화 기법으로 interlock~ 으로 시작하는 함수들은 함수를 실행하는데 원자적 실행을 보장해 동기화를 보장함
뮤텍스 : 값이 signal 과 nonsignal로 이루어져 있고, 뮤텍스를 스레드가 소유 ( 세마포어는 스레드가 소유하지 못함 ) 하게 되면, nonsignal로 바뀌고 락을 해제하게 되면 다시 signal상태로 바뀌는 동기화 기법이다.
세마포어 : 세마포어는 뮤텍스와 달리 0이상의 시그널을 가질 수 있으며, 시그널이 0이 될 때까지 해당 영역안에 스레드를 받을 수 있다. 또한 세마포어안에 있는 스레드가 아닌 다른 스레드들도 signal을 조절 가능하다.
Event같은 경우 0과 1의 signal밖에 가지지 못하기 때문에 다른 스레드가 signal을 빠르게 보내게 되면 해당 작업은 수행을 하지 못하게 되는 현상이 발생하는데, 세마포어는 signal값을 조절할 수 있기 때문에 이러한 문제를 해결 가능
-> queue처럼 쌓아두고 작업이 가능하다 ( 접근 순서 동기화 해결에 사용 가능 )
이벤트 : 이벤트같은 경우는 0과 1의 값을 가지며 1일 때 signal 상태가 되며 해당 이벤트를 wait함으로 어디까지 진행되었고, 지금 어디서 시작할 상황이다 라는 것을 알려줄 수 있다.