운영체제 & 컴퓨터구조

[OS] #9. 원자성 ( atomic ) & 가시성 ( visibility ) & 코드 재배치

코딩하는상후니 2022. 9. 13. 21:21

 

 


 

 

* 원자성 ( Atomic )

 
 
=> 더 이상 쪼개지지 않는 연산.
 
예를 들어,

 

int a = 0;
++a;

 

 

 

 

++a; 부분을 디스 어셈블리로 보게 되면 총 3줄에 걸쳐 나온다.
 
eax 에 값을 가져와서
inc 증가시키고
다시 eax 값을 [a] 에다 넣는다.
 
 
=> 이 때,
위 3단계 사이로 다른 쓰레드들이 접근해 값을 수정할 수 있는 여지가 생긴다는 말.
이 경우, '원자성을 보장하지 못한다' 라고 말하고
 
 
위 3단계를 하나의 연산으로 취급해 실행하는 것을
 
'원자성을 보장한다.' 라고 한다.

 

 

 
=> 원자성을 보장 받기 위해서 atomic 에 관한 명령이나 변수를 선언한다.
 
atomic 명령들은 내부적으로 CPU 의 도움을 받아
 
실행 중간에 간섭 받거나 중단되지 않는다.
 
또, 같은 메모리 영역에 대해 동시에 실행되지 않는다.
 
 
 
 
 
 
즉,
 
 
어떤 쓰레드가 atomic 한 명령들을 실행할 때는 그 중간에
 
문맥교환 ( Context Switching ) 이 발생하지 않게 하고 이로 인해 원자성을 보장함으로써
 
( 중간에 끼어들 틈이 없음. ) 데이터의 일관성을 유지할 수 있다.
 
 
설령 멀티 코어 환경에서,
 
해당 atomic 명령어를 동시에 실행시켰다고 할지라도
 
CPU 레벨에서 알아서 순서를 맞추도록 보장한다.
 
 
 
 
 
 
 
 
 
 
 
 

* 가시성 ( Visibility )

 

 

 

 

=> '쓰레드가 수정한 값이 다른 쓰레드에게도 동일하게 읽히는가' 를 기준한다.
 
만약 그렇다면,
이 때, '가시성을 보장한다' 라고 말한다.
 
 

 

 
=> CPU Core 마다 독립적인 캐시 메모리를 가지고 있다.
 
 
=> 쓰레드의 수정한 값이 재대로 읽혀지지 않는 상황은 두 가지 정도 있겠다.
 
 
1. 이전의 값이 캐시 메모리에 올려져있어서,
해당 값이 바뀌었음에도 불구하고 쓰레드가 캐시 메모리의 값을 쓰는 상황.
 
 
2. 해당 쓰레드의 연산을 캐시 메모리에만 적용시키고 RAM 에는 갱신하지 않는 상황.
 
 
 
 
 
 
 
 
 
 
 
 

* 코드 재배치 & 컴파일러 최적화

 

 

 

 

=> 일전에 CPU 단원에서 설명한 그림이다.
 
 
 
CPU 는 한 클럭당 처리할 수 있는 작업의 수가 하나가 아닐 수 있다.
 
따라서,
명령어를 여러 줄을 가져와서 실행할 때,
CPU 의 최적화 기준에 따라서 우리의 기준으로 짜여진 순서가 뒤바뀔 수 있다.
 
 
 
=> 컴파일러도 마찬가지로,
컴파일러의 기준으로 최적화를 진행할 여지가 있다.