메모리 배리어(memory barrier)는 중앙 처리 장치나 컴파일러에게 특정 연산의 순서를 강제하도록 하는 기능이다.
중앙 처리 장치에서는 비순차적 명령어 처리 기법을 통해 연산 결과에 영향이 가지 않도록 연산의 순서를 뒤바꿀 수 있으며, 컴파일러에서도 역시 비슷한 최적화를 수행한다. 하지만, 이러한 기능은 여러 스레드가 동시에 돌아가는 경우, 코드의 실행 순서가 바뀌어 실행되는 동안 다른 스레드에서 그 부분에 대한 메모리를 접근하여 잘못된 결과를 내놓을 수 있다.
따라서 특정 부분에 대하여 실행 순서를 강제하는 메모리 배리어를 놓아야 한다.
예제
다음의 코드는 메모리 배리어가 없는 경우 의도하지 않은 동작을 실행하게 된다:
(스레드 1)
while(x==0) { }
// 여기에 메모리 배리어가 필요함
print y;
|
(스레드 2)
y = 10;
// 여기에 메모리 배리어가 필요함
x = 1;
|
여기에서 스레드 1의 print y;
가 원래 의도대로 10을 출력하려면 그 위에서 x==0
조건이 통과해야 한다. 하지만, 스레드 2에서 y = 10;
와 x = 1;
는 서로 의존성이 없기 때문에, 컴파일러나 CPU가 이 두 연산의 순서를 바꾸는 경우도 있다. 마찬가지로, 스레드 1에서 print y;
에서 변수 y의 값을 읽어들이는 동작이 while(x==0)
에서 x의 값을 읽어들이는 동작보다 먼저 일어나는 경우도 있다. 두 명령 사이에 메모리 배리어를 설치함으로써 컴파일러나 CPU가 두 명령의 순서를 지키도록 강제하여 원하는 결과를 얻을 수 있다.
하드웨어 지원
x86과 x86-64 CPU에서는 서로 종속성이 없는 메모리 연산의 순서가 보장되지 않으며, 이를 보장하기 위한 SFENCE, LFENCE, MFENCE 명령어가 존재한다.[1]
같이 보기
각주
외부 링크