이 문서는 2022년 12월 1일에 @kwanyung에 의해서 작성되었습니다.
1. 동기화
1.1 동기화란?
1.2 스레드 동기화
1.3 동기화 객체의 종류
2. 크리티컬 섹션(임계 구역)
3. 커널 모드 동기화
3.1 뮤텍스
3.2 세마포어
4. 뮤텍스와 세마포어의 차이
사전 뜻 : 작업들 사이의 수행 시기를 맞추는 것.
- 컴퓨터와 스마트폰 사이 사진과 영상 자료를 서로 동일하게 만드는 작업을 시행할 경우 컴퓨터와 스마트폰이 동기화 된 것.
동기화가 왜 필요할까?
- 한 쪽의 기기에 이상이 생겨도 다른 쪽의 기기가 멀쩡하다면 동기화 된 데이터를 활용 가능!
- Notion의 경우 PC에서 사용하면 모바일 환경에서 동기화된 데이터를 사용할 수 있음.
기본적으로 스레드가 안전하지 않은 상태는 공유하는 자원을 활용하는 과정에서 발생함.
- 스레드 동기화가 필요한 경우
- 둘 이상의 스레드가 공유 자원에 접근하려고 하는 상황
- 한 스레드가 작업을 완료하고 대기 하고있는 스레드에게 알려줘야 하는 상황.
이 상호 작용을 스레드 사이의 중간 매개체가 담당하고 이 역할을 할 수 있는 것을 동기화 객체(Synchronization Object)라고 하는 것.
두 가지 관점에서의 스레드 동기화
- 실행순서의 동기화
- 스레드의 실행순서를 정의하고 이 순서를 따르도록 하는 것이 스레드 동기화
- 메모리 접근에 대한 동기화
- 한 순간에 하나의 스레드만 접근해야 하는 메모리 영역이 존재
- 데이터 영역에 할당된 변수를 둘 이상의 스레드가 동시에 접근하면
스레드 안전하지 않음
- 이렇게 메모리 접근에 있어 동시 접근을 막는 것 또한 스레드의 동기화에 해당
실행순서는 순서가 정해져있고 순서가 지켜져야함.
메모리 접근은 실행 순서가 중요한게 아니라 한 순간 하나의 스레드만 접근하면 되는 상황.
- 대기하고 있는 스레드가 진행 가능한지 여부를 판단!
- 유저 모드 동기화
- 동기호 과정에서 커널 코드가 실행되지 않는 동기화 기법
- 동기화를 위해 커널 모드로 전환을 할 필요가 없지만(성능 향상) 기능상의 제한도 생김.
- 커널 모드 동기화
- 커널에서 제공하는 동기화 기능을 활용하는 방법.
- 동기화에 관련된 함수가 호출될 때 마다 커널 모드로의 변경이 필요하고, 이는 성능 저하로 이어짐.
- 하지만 유저 모드 동기화보다 많은 기능을 제공받음.
임계 구역(Critical Section)은 배타적 접근(한 순간에 하나의 스레드만 접근)이 요구되는 공유 리소스(ex: 전역 변수)에 접근하는 코드 블록
- 즉, 문제의 원인이 되는 코드 블록을 임계영역이라고 하는 것.
공유 데이터를 여러 프로세스가 동시에 엑세스하면 시간적인 차이 등으로 인해 잘못된 경과를 만들 수 있기 떄문에 한 프로세스가 임계 구역을 수행하고 있을 때는 다른 프로세스/스레드는 이를 활용할 수 없게 만들어야 함.
- 커널 모드 동기화는 유저 모드 동기화에 비해 느리다.
- 유저 모드에서 커널 모드로, 커널 모드에서 유저모드로 전환이 필요하기 때문.
상호 배제(Mutual Exclusion)(두 처리 단위가 임계 구역에 동시에 접근하지 못하도록 막는 기법)를 줄여서 뮤텍스 라고 하는 것.
뮤텍스는 공유된 자원의 데이터 혹은 임계 구역등에 하나의 프로세스/스레드가 접근하는 것을 막아줌.(동기화 대상이 하나)
lock: 현재의 임계 구역에 들어갈 권한을 얻어온다. 만일 다른 프로세스/스레드가 임계 구역을 수행 중이라면 종료할때까지 대기한다(entry section). unlock: 현재의 임계 구역을 모두 사용했음을 알린다. 대기중인 다른 프로세스/스레드가 임계 구역에 진입할 수 있다(exit section).
- 마치 식당에 있는 화장실에 사람이 있으면 다른 손님이 화장실을 이용할 수 없는 것 처럼 임계 구역에 다른 프로세스/스레드가 있다면 대기하는 방법!
- 멀티프로그래밍 환경에서 공유 자원에 대한 접근을 제한하는 방법으로 사용되고 모든 교착 상태를 해결하지는 못함.
- 하나의 공유되는 자원에 제한된 개수의 프로세스/스레드만 접근할 수 있도록 하는 방식.
세마포어는 공유된 자원의 데이터 혹은 임계 구역등에 여러 프로세스/스레드가 접근하는 것을 막아줌.(동기화 대상이 하나 이상)
-
세마포어는 원자적으로 제어되는 정수 변수
기본적으로 뮤텍스에 기반하며 일반적으로 세마포어의 값이 0이면 자원에 접근할 수 없도록 블락, 0보다 크면 접근함과 동시에 세마포어의 값을 1 감소시킴.
반대로 종료하고 나갈 때는 세마포어의 값을 1 증가시켜 다른 프로세스/스레드가 접근할 수 있도록 만들어 줌. -
마치 식당에 화장실이 여러개가 있고
현재의 빈 화장실을 알려주는 숫자(세마포어)
를 이용해 손님에게 현재 빈 화장실의 수를 보여주고 손님이 들어가고 나올 때마다 수를 변환 시키는 것과 같음.
- 가장 큰 차이는
동기화 대상의 갯수
- 뮤텍스를 동기화 대상이 1
- 세마포어는 동기화 대상이 1 이상
- 세마포어는 뮤텍스가 될 수 있지만 뮤텍스는 세마포어가 될 수 없음.
- 뮤텍스는 0, 1로 이루어진 이진 상태를 가지므로 Binary Semaphore!
- 세마포어는 프로세스/스레드를 소유할 수 없지만 뮤텍스는 소유가 가능하고 이에 대한 책임을 짐.
- 뮤텍스는 뮤텍스를 소유하는 스레드가 뮤텍스를 헤제할 수 있지만 세마포어는 세마포어를 소유하지 않는 스레드가 세마포어를 헤제할 수 있음.
뮤텍스와 세마포어에 대한 깊은 지식은 다음주에!