운영체제 6-2. 동기화를 위한 하드웨어의 지원(TAS, CAS, Java - AtomicInteger)

Jang990·2023년 12월 21일
0

운영체제

목록 보기
5/9

앞 글에서 동기화 문제를 해결하는 소프트웨어 알고리즘인 피터슨 알고리즘을 알아봤고,
해당 알고리즘의 한계를 살펴보며 하드웨어의 지원이 필요한 이유를 알아봤다.

이 글에서는 하드웨어의 지원을 살펴본다.

이 글에서는 특정 기계에서 다루는 특정 명령어가 아닌
test_and_set(), compare_and_swap()이라는 추상화한 명령어를 통해서
이런 유형의 명령어들의 주요 개념을 알아보는 것이 목표이다.

하드웨어의 지원

컴퓨터에서 한 클럭에 원자적으로 실행되는 연산인 test_and_set(), compare_and_swap()를 살펴보자.

가장 중요한 것은 아래에서 언급하는 명령어들이 하드웨어가 지원해서 한 클럭에 원자적으로 실행된다고 생각하는 것이다.

하드웨어에 test_and_set(), compare_and_swap()을 한 클럭에 처리하기 위한 특정 모듈이 만들어져있다고 생각하자.

아래의 사진에 인출, 해석, 실행, 저장 등과 같은 명령어인 test_and_set(), compare_and_swap()가 있다고 생각하면 쉬울 것이다.

test_and_set()compare_and_swap()도 CPU에서 실제 사용하는 명령어가 아니라 인출, 해석등과 같이 추상화된 명령어 이다.

test_and_set() - TAS

간단하다. target의 값을 true로 바꾸고 바꾸기 이전의 값을 출력해주는 것이다.

항상 기억하자. 이 함수는 한 클럭안에서 원자적으로 전부 처리된다.

TAS를 사용한 상호배제를 만족하는 코드(알고리즘)

이 명령어를 통해서 상호배제를 구현하는 알고리즘을 구현한다면 다음과 같이 코드를 짤 수 있다.

lockfalse일 때
test_and_set()에 들어가면 locktrue로 바뀌고 false가 반환된다.
while문은 false가 반환되어 무시되고 임계구역에 진입하게 된다.
마지막으로 임계구역을 나왔을 때 lockfalse로 바꾸는 것을 주목하자.

locktrue일 때
test_and_set()에 들어가면 locktrue를 다시 넣고 true가 반환된다.
즉 여기서 while문을 돌면서 대기한다.

이를 통해 상호배제를 만족할 수 있게 된다.
상호배제를 만족했다는 것이지 임계구역 문제 해결을 위한 3가지 요구사항을 모두 만족한 것은 아니다.

compare_and_swap() - CAS

value의 값이 expected와 맞다면 new_value의 값을 넣어준다.
그리고 값을 넣기 전 value 값을 반환한다.

항상 기억하자. 이 함수는 한 클럭안에서 원자적으로 전부 처리된다.

CAS를 사용한 상호배제를 만족하는 코드(알고리즘)

이번에는 CAS를 통해서 상호배제를 구현하는 알고리즘을 구현한다면 다음과 같이 코드를 짤 수 있다.

lock0일 때
compare_and_swap()에 들어가면 lock1로 바뀌고 0이 반환된다.
while문은 false가 되어 무시되고 임계구역에 진입하게 된다.

lock1일 때
compare_and_swap()에 들어가면 1이 반환된다.
즉 여기서 while문을 돌면서 대기한다.

이를 통해 상호배제를 만족할 수 있게 된다.

Intel x86 아키텍처에서 어셈블리 명령어 cmpxchg가 compare_and_swap() 명령어를 구현하는데 사용된다.

상호배제 이외의 조건들도 만족하는 코드는 책에서 다루고 있으니 책을 확인하자.

원자적(Atomic) 변수

앞서 살펴본 CAS 명령어는 상호배제를 구현하기 위해 직접 사용되지 않고,
임계구역 문제를 해결하는 다른 도구를 구축하기 위한 기본 구성요소로 사용된다.

임계구역 문제를 해결하는 그런 도구 중 하나는 원자적 변수이다.
원자적 변수를 제공하는 대부분의 시스템은 CAS 연산을 사용하여 구현된다.

void increment(atomic_int *v)
{
	int temp;
    do {
    	temp = *v;
    } while(temp != compare_and_swap(v, temp, temp+1));
}

CAS 명령어의 동작을 이해하고 있다면 해당 코드도 어느정도 이해가 될 것이다.
결과적으로 해당 코드에서 v는 원자적으로 1이 증가되는 것이 보장된다.

Java - AtomicInteger

자바에서 제공하는 AtomicInteger의 코드를 확인해보자.
AtomicInteger에서 제공하는 incrementAndGet 메소드의 코드를 타고 들어가면 다음과 같은 코드를 확인할 수 있다.

increment 함수와 매우 유사한 코드를 볼 수 있다.

마무리

6-1에서 임계영역 문제를 인식했고, 해당 문제를 해결하기 위해서는 하드웨어적인 지원이 필요함을 깨달았다.
그리고 그 지원의 종류로 TAS와 CAS 하드웨어 명령어를 살펴봤다.

하지만 임계구역 문제를 해결하기 위해 이 명령어들을 응용 소프트웨어 프로그래머들이 직접 가져다가 쓰는 방식은 매우 복잡하고 어렵다.
그래서 상위 수준의 소프트웨어 도구(Tool)들을 개발하게 된다.

이 소프트웨어 도구들이 뮤텍스, 세마포어, 모니터이다.
다음 글에서 이 도구들을 살펴본다.

참고 및 사진 출처

도서 - 운영체제
인프런 - 운영체제 공룡책 강의
https://jooona.tistory.com/13

profile
공부한 내용을 적지 말고 이해한 내용을 설명하자

0개의 댓글