봉화희제후: 주유왕이 제후들을 놀리기 위해 거짓으로 봉화를 올리다가, 제후들이 진짜 적들이 침공했을 때에도 봉화를 믿지 않게되어 멸망한 사건
고전적인 스레드의 동기화는 본질적으로 위 사례의 봉화와 같다.
이 상황을 아래와 같은 코드로 표현 할 수 있다.
bool is_enemy_coming = false;
int enemy_num = 0;
void king_thread()
{
enemy_num = 100000;
is_enemy_coming = true;
}
void other_thread()
{
int n;
if(is_enemy_coming)
{
n = enemy_num;
}
}
사견
최적화와 성능 향상을 위해, CPU(하드웨어)는 때로 명령어의 실행 순서를 변경한다.
컴파일시 코드가 재정렬되는 예시
C++ 코드
int a;
int b;
void main()
{
a = b + 100;
b = 200;
}
컴파일러가 생성한 어셈블리 코드
ov 0x200b54($rip),%eax # %eax = b
dd $0x64,%eax # %eax = %eax + 100
ov %eax,0x200b4f(%rip) # a = %eax
ovl $0xc8,0x200b41(%rip) # b = 200
생성 과정에서 최적화를 실행한 어셈블리 코드
ov 0x200b54($rip),%eax # %eax = b
ovl $0xc8,0x200b41(%rip) # b = 200 <--- 이 부분의 순서가 변경됨
dd $0x64,%eax # %eax = %eax + 100
ov %eax,0x200b4f(%rip) # a = %eax
CPU의 기계명령어 실행시 순서가 조정되는 예시
기본적인 CPU의 명령어 실행 과정(유휴시간 존재)
CPU의 명령어 실행 순서가 조정되는 과정(유휴시간 최소화)
위와 같은 과정을 통해 CPU는 명령어의 실행 순서를 조정할 수 있으며, 이를 OoOE(Out-of-Order Execution)이라고 한다.
CPU가 작업 시 캐시에 직접 기록하지 않고, 저장 버퍼를 둔다.
CPU의 명령어 실행시 데이터의 기록은 비동기로 이루어진다.
이로인해 아래와 같은 현상이 발생한다.
a = 1; // 수정된 값이 버퍼에 우선 저장되고, 잠시 후 캐시에 반영된다. 이후 캐시가 동기화되기까지 시간이 걸린다.
b = y;