My Study/System

Critical Section(임계 영역) - Interlocked

  크리티컬 섹션에 이어서 두번째는 Interlocked이다.


  Interlocked(이하 인터락) 함수는 내부적으로 한 순간에 하나의 쓰레드에 의해서만 실행되도록 동기화가 되어있다. 


LONGLONG __cdecl InterlockedIncrement64(
  _Inout_ LONGLONG volatile *Addend
);
출처 : InterlockedIncrement64 MSDN


  이 API는 카운트를 1씩 증가시키는 인터락 함수이다. 어떻게 작동하는 것인지 궁금하여 vs 어셈블리어로 보았더니 달랑 한줄이였다.



  lock inc 라는 어셈블리어로 이루어져있다. 

  lock 이란 어셈블리는 BUS에 LOCK# 신호가 전송되고, 그러면 현재 프로세서를 제외한 다른 다른 프로세서가 공유 메모리에 접근하는 것을 순간적으로 차단한다. 

(이부분은 Intel64 , IA-32 아키텍쳐 소프웨어 개발 메뉴얼에 영어로 적혀있길래 그냥 스스로 의역을 한거에요 틀릴 수도...)

  inc는 카운트를 1 증가 시키는 어셈블리로 이 API를 사용하면 크리티컬 섹션처럼 사용하게 되는 것처럼 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
LONGLONG volatile Count = 0;
 
unsigned int WINAPI ThreadProc1(LPVOID lpParam)
{
 
    for (DWORD i = 1; i <= 1000; i++)
    {
        Sleep(1);
        InterlockedIncrement64(&Count);
    }
 
    return 0;
}
 
unsigned int WINAPI ThreadProc2(LPVOID lpParam)
{
    
    for (DWORD i = 1; i <= 1000; i++)
    {
        Sleep(1);
        InterlockedIncrement64(&Count);
    }
    return 0;
}
 
int _tmain()
{  
    //코드 생략...
}
 
cs

  

  크리티컬 섹션을 사용한 것처럼 결과 값이 2000 이 제대로 나오게 된다.

[위의 예제 코드를 보면서 정말 코드 못짜는거 같아,,, 나중에 수정할게요 ㅠㅠ]


인터락 함수에 대한 것은 여기까지만 읽으시면 됩니다~ 이 아래는 그냥 추가로 공부한 것들입니다.


  이 API를 보면서 가장 궁금했던 것이 volatile 이다. 이건 무엇일까??

  volatile은 C / C++ 의 ANSI 표준 키워드로 최적화를 수행하지 않게 하는 의미로도 사용된다.(잘 사용이 안된다고 하는데... 혹시 모르니까 공부해보자) 아래 예제를 보면서 생각을 해보자.


-------사용자-------

*(unsigned int *) 0xDEADBEEF = 0x10

*(unsigned int *) 0xDEADBEEF = 0x11

*(unsigned int *) 0xDEADBEEF = 0x12

*(unsigned int *) 0xDEADBEEF = 0x13


-------컴파일러-------

*(unsigned int *) 0xDEADBEEF = 0x13


  이 예제에서 보면 사용자가 의도한 것이 0x10 ~ 0x13까지 0xDEADBEEF 라는 공간에 순차적으로 넣는 것인데 컴파일러는 바로 0x13으로 넣음으로써 코드를 간략화 시켰다. 물론 코딩을 잘못하여 컴파일러가 의도한 것처럼 한 것일 수 있지만, 만약 각각 숫자에 의미가 있고 그에 해당하는 것이 실행한다고 하면 0x13에 해당하는 행위밖에 실행을 하지 못 할 것이다. 이 사태를 방지하는 것이 volatile 이다. 

최근 트랙백

알림

이 블로그는 구글에서 제공한 크롬에 최적화 되어있고, 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.