volatile 변수 선언

     

- volatile?


C언어에서 volatile이 무엇인가요? 라는 질문을 들어본적이 있습니다.

거의 10년전, 대학교 1학년 때부터 C언어를 배우고, 사용해 왔는데 엄청 생소한 단어였습니다. 물론 전공책에서 지나가다가 본적은 있겠지만, 개념만 한번 읽고 그냥 넘어갔을 것 같습니다. 


구글에서 volatile을 검색해보면 wiki에 이렇게 정의되어 있습니다.



" C/C++ 에서 컴파일러의 최적화를 제한하는 역할을 한다. "



음.. 그렇군! 컴파일러의 최적화를 막는거군~! .. 그래서 왜 막는거죠..?

일단 컴파일러의 최적화부터 알아봐야 할 것같습니다.



- 컴파일러의 최적화


우리가 작성한 코드를 컴파일해주는 컴파일러는 아주 똑똑한 녀석입니다. 우리가 짠 코드가 조금이라도 좋은 성능을 보일 수 있도록 코드를 수정합니다. 이러한 행동을 컴파일러 최적화 (optimizing compiler)라고 합니다.


자 그럼 어떤 경우에 컴파일러 최적화가 일어날까요?


1
2
3
4
5
6
7
8
void test(int a)
{
    int b;
 
    b = a; // 1:
    b = a; // 2:
    b = a; // 3:
}
cs


위와 같은 test라는 함수가 있습니다. b라는 변수에 a라는 값을 여러번 대입하고 있지요. 주석을 통해 임의로 b = a의 순서를 정했습니다. 1~3번까지의 b = a가 있지만, 컴파일러는 이 코드들이 같은 의미로 반복된다고 생각하고 하나로 압축합니다. 결국 3개의 b = a 는 1개의 b = a;로 최적화됩니다.


1
2
3
4
5
6
void test(int a)
{
    int b;
 
    b = a; // 3:
}
cs


간단히 생각해보면 b = a 라는 연산이 연속해서 3번 들어가는 것은 아주 불필요한 반복입니다. 1번을 하든 3번을 하든 b에는 a값이 들어가기 때문이죠. 하지만 외부에서 a값이 바뀐다면 어떨까요? 이해하기 쉽게 그림으로 그려보도록 하죠.



위 그림처럼 a라는 공간에는 10이라는 숫자가 들어있습니다. b  = a 를 하면 b 역시 a에 있는 10이 되어서 b = 10이 됩니다. 만약 첫 번째 b = a 연산이 끝나고, 외부에 어떤 프로그램이 a의 값을 10에서 20으로 바꾼다면 어떨까요?

그럼 두 번재와 세 번째의 b = a연산에서 a는 20이기 때문에 b = 20이 됩니다.

즉 같은 b = a라는 연산임에도 불구하고, 첫 번째는 b = 10, 두 번째는 b = 20이 됩니다. 같은 연산이 반복적으로 쓰였지만, 외부에서 값이 변동하였기 때문에 다른 연산이 되어버립니다. 하지만 컴파일러는 이것을 인식하지 못하고 3개의 연산을 같은 연산으로 생각하고 1번으로 줄이게 됩니다. 이 때 volatile을 선언하면 컴파일러의 최적화를 막을 수 있습니다.



- visibility(가시성)


또 volatile은 다음과 같은 멀티 쓰레드 상황에서도 사용될 수 있습니다.


1
2
3
4
5
6
7
8
9
10
void foo(int idx)
{
 
    idx = 99;
 
    while(idx != 100)
    {
        //언제 종료?
    } 
}
cs


foo함수는 실행되면 idx = 99을 실행하고 idx가 100이 될때까지 무한 루프작업을 실행합니다. 


1
2
3
4
5
 
void stopfoo(int *idx)
{
    *idx = 100;     
}
cs


stopfoo함수는 실행되면 idx값을 100을 만듭니다. 한쪽 쓰레드에서 foo함수가 실행중일 때, 다른쪽 쓰레드에서 stopfoo를 실행시키면 어떻게 될까요? idx값을 100으로 만들어 주기 때문에 foo함수가 종료될까요?


하지만 그렇게 되지 않습니다. 왜냐하면 stop을 구동하고 있는 쓰레드에게는 idx값은 99로 고정되어 있기 때문이죠. 즉, 외부에서 idx값에 접근하여 값을 바꿀 수 있다는 것을 컴파일러는 인지하지 못합니다. 여기서 volatile로 명시해 준다면 컴파일러는 idx값이 외부로부터 바뀔 수 있다는 것을 인지하고, 매번 idx를 호출할 때 그 값을 체크하게 됩니다. 이렇게 외부에서 해당 값의 변화를 볼 수 있도록 해주는 것을 visibility(가시성)이라고 합니다. 값이 변하는게 보인다는 뜻이지요.



- volatile 정리


volatile은 다음과 같은 상황에서 사용될 수 있습니다.


1. 메모리 맵 I/O

2. 인터럽트 서비스 루틴

3. 멀티쓰레드


3가지 모두 외부에서 특정값을 변경시키는 상황입니다. C에서 volatile은 외부에서 특정 값을 변화시킬 수 있다는 것을 컴파일러가 알 수 있도록 정의하는 역할이라고 정리할 수 있습니다.



반응형

댓글

Designed by JB FACTORY