STL ( Standard Template Library ) 컨테이너

  • STL 컨테이너 종류로는 시퀀스 컨테이너, 어댑터 컨테이너, 연관 컨테이너가 있습니다.




시퀀스 컨테이너

list

  • list 는 이중 링크드 리스트로 구현된 컨테이너입니다.

 

장점

  • 정렬이 가능합니다.
  • 중간에 데이터를 삽입하거나 삭제할 때 새롭게 연결만 해주면 되기 때문에 오버헤드가 적습니다.
  • 저장할 요소의 개수를 미리 알 수 없을 때 사용하기에 적합합니다.

 

단점

  • 랜덤 액세스가 불가능합니다.
  • 순회할 때 스페이셜 로컬리티의 이점을 얻을 수 없습니다.

 

사용하기 적합한 경우

  • 저장한 요소의 개수가 빈번하게 변화할 때
  • 삽입, 삭제가 빈번하게 발생될 떄
  • 랜덤 액세스가 필요하지 않을 때



vector

  • vector 는 배열로 구현된 컨테이너입니다.
  • 저장할 요소의 개수가 최대 크기를 넘어설 경우 현재 크기의 *2 만큼의 배열을 새로 확보한다.

 

장점

  • 정렬이 가능합니다.
  • 인덱스를 이용한 랜덤 액세스가 가능합니다.
  • 순회할 때 스페이셜 로컬리티의 이점을 얻을 수 있습니다.

 

단점

  • 중간에 데이터를 삽입하거나 삭제할 때 복사 오버헤드가 발생합니다.
  • 저장할 요소의 개수가 현재 컨테이너 크기보다 클 경우 새롭게 메모리를 확보하고 복사하는 오버헤드가 발생합니다.

 

사용하기 적합한 경우

  • 저장할 요소의 개수가 일정할 때
  • index를 이용한 랜덤 액세스가 필요할 때
  • 잦은 순회가 필요할 때




어댑터 컨테이너

stack

  • LIFO ( Last in first out ) 의 특징을 가진 컨테이너입니다.



queue

  • FIFO ( First in first out ) 의 특징을 가진 컨테이너입니다.



priority_queue

  • 힙 자료구조의 컨테이너입니다.




연관 컨테이너

map, set

  • 자가 균형 이진 탐색트리인 레드-블랙 트리로 구현된 컨테이너입니다.
  • key, value 를 한 쌍으로 저장하는 컨테이너입니다.
  • multimap, multiset 을 이용하면 중복 key 저장이 가능합니다.

 

장점

  • key를 기준으로 정렬이 가능합니다.
  • 랜더 액세스가 가능합니다.

 

단점

  • 시간 복잡도가 O(log N) 으로서 저장하는 데이터가 많아질 수록 검색 성능이 떨어집니다.

 

사용하기 적합한 경우

  • key를 이용한 랜덤 액세스가 필요할 때
  • key를 기준으로 정렬이 필요할 때



unordered_map, unordered_set

  • 해쉬 테이블로 구현된 컨테이너입니다.
  • key, value 를 한 쌍으로 저장하는 컨테이너입니다.
  • unordered_multimap, unordered_multiset 을 이용하면 중복 key 저장이 가능합니다.

 

장점

  • key 해쉬를 이용한 랜덤 액세스가 가능하기 때문에 저장할 요소의 개수의 상관없이 일정한 검색 시간 복잡도를 가집니다.

 

단점

  • 정렬이 불가능합니다.
  • 저장할 요소의 개수가 적다면은 오히려 해쉬 함수로 인해 성능이 떨어질 수 있습니다.
  • 해쉬 충돌이 발생될 경우 그만큼 검색 시간 복잡도가 증가합니다.

 

사용하기 적합한 경우

  • key를 이용한 랜덤 액세스가 필요할 때
  • 정렬이 필요하지 않을 때
  • 많은 양의 데이터를 저장해야 할 때
  • 많은 양의 데이터를 저장해도 일정한 검색 시간 복잡도를 원할 때




STL 컨테이너 비교

컨테이너 자료구조 검색 시간 복잡도 랜던 액세스 정렬
list 이중 링크드 리스트 O ( N ) X O
vector 배열 O ( 1 ) O O
map, set 레드-블랙 트리 O ( log N ) O O
unordered_map, unordered_set 해쉬 테이블 O ( 1 ) O X

STL ( Standard Template Library ) 이란?

  • STL은 일반적으로 많이 사용되는 자료구조와 알고리즘을 모은 표준 템플릿 라이브러리입니다.
  • STL은 반복자, 알고리즘, 함수자, 컨테이너라고 불리는 네 가지의 구성 요소를 제공합니다.




Template 과 Generic Programming

  • 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하여 코드의 재사용성 및 다형성의 이점을 얻을 수 있는 프로그래밍 기법입니다.

Template

  • Template 은 C++ 에서 Generic Programming 기법을 사용할 수 있는 기능입니다.




STL 반복자 ( iterator )

  • STL 은 일관적으로 STL 컨테이너를 접근할 수 있는 iterator 라고 불리는 반복자를 제공합니다.

iterator 를 사용하는 이유

  • iterator 를 통해서 STL이 제공하는 컨테이너를 일관적인 방법으로 접근할 수 있습니다.




STL 알고리즘

  • STL 은 min_elementPermalink ( 최솟값 ), max_elementPermalink ( 최댓값 ), sort ( 정렬 ), find ( 요소 찾기 ), erase ( 요소 삭제 ) 등의 STL 컨테이너를 대상으로 사용할 수 있는 알고리즘 함수들을 제공합니다.




STL 함수자 ( functor )

  • STL은 plus, minus, multiplies, divides 와 같은 산술 연산 함수자 그리고 equal_to, not_equal_to, greater, less 등과 같은 비교 연산 함수자를 제공합니다.

사용 예시

  • priority_queue<int, vector<int>, greater<int>> pq; 와 같이 사용해서 낮은 숫자가 가장 먼저 pop 될 수 있도록 할 수 있습니다.




STL 컨테이너

  • STL은 시퀀스, 연관, 어뎁터 컨테이너를 제공합니다.

시퀀스 컨테이너

  • 시퀀스 컨테이너는 데이터를 선형을 저장하고 관리하는 형태의 컨테이너를 말합니다.
  • list, vector, deque, forward_list, array 등이 있습니다.

 

어뎁터 컨테이너

  • 기존 컨테이너를 랩핑하여 스택과 큐 같은 인터페이스의 제한을 둔 컨테이너를 말합니다.
  • stack, queue, priority_queue 등이 있습니다.

 

연관 컨테이너

  • key 와 value 를 묶어 데이터를 하나의 쌍으로 저장하는 컨테이너를 말합니다.
  • map, multimap, set, multiset, unordered_map, unordered_multimap, unordered_set, unordered_multiset 등이 있습니다.

컴퓨터 구조

  • 컴퓨터 구조 지식은 크게 컴퓨터가 이해하는 정보, 컴퓨터의 네 가지 핵심 부품 두 가지로 분류할 수 있습니다.




컴퓨터가 이해하는 정보

  • 컴퓨터는 전류의 흐름 여부에 따라서 0과 1로 구분하고, 이를 통해 얻게된 0과 1 정보를 해석하여 처리합니다.

정보의 종류

  • 컴퓨터가 이해하는 정보의 종류에는 데이터명령어가 있습니다.

데이터 ( Data )

  • 숫자, 문자, 이미지, 동영상과 같은 정적인 정보를 가리켜 데이터 ( Data ) 라고 합니다.

명령어 ( Instruction )

  • 컴퓨터에게 명령하여 데이터 읽기, 쓰기를 통해서 조작하도록 요청하는 정보를 명령어 ( Instruction ) 이라고 합니다.




컴퓨터의 네 가지 핵심 부품

  • 컴퓨터의 핵심 부품은 CPU ( Central Processing Unit ), 주기억장치 ( Main Memory ), 보조기억장치 ( Secondary Storage ), 입출력장치 ( Input/Output device ) 정도로 정리할 수 있습니다.

CPU ( Central Processing Unit )

  • CPU 는 컴퓨터의 두뇌역할로서 메모리에 저장된 명령어를 Fetch하고 Decode 하고 Excute 하는 부품입니다.
    CPU 의 핵심 구성요소로는 CU( Control Unit ),산술논리연산창지( Arithmetic Logic Unit ), 레지스터 ( Register )가 있습니다.

CU ( Control Unit )

  • CU는 명령어를 Decode 하고 Decode한 명령어를 통해 제어 신호를 보내 ALU에게 어떤 연산을 하거나 메모리에 저장된 데이터를 읽거나 쓰기 명령을 할 수 있습니다.

산술논리연산장치 ( Arithmetic Logic Unit )

  • CU에서 Decode한 연산 명령어를 Excute 하는 역할을 하는 부품입니다.

레지스터 ( Register )

  • CPU가 연산에 필요한 데이터, 주소, 매개변수( 함수 호출 규약에 따라 다름 ), 스택 프레임 등을 임시로 저장하는 가장 빠른 저장 장치입니다.




주기억장치 ( Main Memory )

  • 주기억장치는 현재 실핼되는 프로그램의 명령어데이터를 저장하는 역할을 합니다.




보조기억장치 ( Secondary Storage )

  • 주기억장치는 전원이 꺼질 경우 모든 데이터를 잃지만 보조기억장치는 전원이 꺼져도 저장된 데이터를 유지합니다. 주기억장치보다는 용량대비 저렴하지만 상대적으로 느립니다.

페이징 파일

  • 페이징 파일을 이용해서 주기억장치의 부족한 용량을 보조역할을 할 수 있습니다.




입출력장치 ( Input/Output device )

  • 입출력장치는 마이크, 스피커, 마우스, 키보드처럼 컴퓨터 외부에 연결되어 컴퓨터 내부와 정보를 교환하는 장치를 말합니다.




메인보드( Main board ) 와 시스템 버스 ( System bus )

  • 컴퓨터의 핵심 부품들은 모두 메인 보드( 혹은 Mother board 라 불림 ) 라는 판에 연결됩니다. 즉 메인보드에 연결된 부품들은 메인 보드의 버스라는 통로를 이용해서 서로 정보를 주고받습니다. 여러 버스 가운데 컴퓨터의 네 가지 핵심 부품을 연결하는 가장 중요한 버스는 시스템( System bus ) 입니다.

시스템 버스 ( System bus ) 구성

주소 버스 ( Address bus )

  • 읽기, 쓰기를 할 메모리의 주소를 주고받는 통로입니다.

데이터 버스 ( Data bus )

  • 명령어와 데이터를 주고받는 통로입니다.

제어 버스 ( Control bus )

  • 메모리를 읽거나 쓰기를 할지 등의 신호를 주고받는 통로입니다.

데드락 ( Deadlock ) 이란?

  • 둘 이상의 쓰레드가 서로 점유하고 있는 자원에 대해서 독점적인 접근을 시도하여 서로 무한정 기다리는 상태를 말합니다.




데드락 ( Deadlock ) 발생 조건

 

상호 배제 ( Mutual exclusion )

  • 자원에 대한 배타적 접근만을 허용하는 것을 의미합니다.




점유와 대기 ( Hold and wait )

  • 특정 자원에 대한 접근 권한을 가진 상태에서 다른 자원에 대한 접근 권한을 기다리는 상태를 의미합니다.




비선점 ( No preemption )

  • 다른 쓰레드가 소유중인 자원에 대해서 선점할 수 없는 것을 의미합니다.




순환대기 ( Circular wait )

  • 각 쓰레드가 누군가 소유중인 자원에 대해서 접근을 시도합니다.




데드락 ( Deadlock ) 재현 방법

 

  • 위 그림과 같이 1, 2번 쓰레드가 서로가 소유하고 있는 자원에 접근을 시도할 경우 100% 데드락 ( Deadlock ) 이 발생됩니다.




데드락 ( Deadlock ) 회피 방법

 

  • 데드락 ( Deadlock )데드락 ( Deadlock ) 발생 조건 에서 하나라도 부합하지 않다면 발생되지 않습니다.




회피 방법 1

  • 중복 락을 제거하고 하나의 락으로 통일합니다.




회피 방법 2

  • 락을 사용하는 자원에 대해서 중복되지 않는 정수의 seed 값을 할당하여 중복 락을 시도하기 전에 정렬하여 락에 대한 순서를 지키도록 합니다.



컨텍스트 스위칭 ( Context Switching ) 이란?

 

  • 컨텍스트 스위칭은 현재 수행중인 쓰레드의 레지지스터 상태를 TCB에 있는 레지스터 데이터 블럭에 백업하고 스케줄러에 의해서 퀀텀 타임을 할당받은 쓰레드의 레지스터 상태 값을 CPU 코어에 업로드하는 일련의 과정을 말합니다.

 

  • 컨텍스트 스위칭은 최대한 적게 발생되는 것이 좋습니다. 유저 모드에서 커널 모드로 전환되고 레지스터 상태 값을 백업하고 다시 업로드 하는 과정으로 인해 오버헤드가 발생되어 성능 하락의 원인이 되기 때문입니다.




컨테스트 스위칭의 종류

  • 컨텍스트 스위칭의 종류로는 쓰레드 컨텍스트 스위칭프로세스 컨텍스트 스위칭이 있습니다.




쓰레드 컨텍스트 스위칭 ( Thread Context Switching ) 이란?

  • 동일한 프로세스 내부에 있는 쓰레드간의 컨텍스트 스위칭 ( Context Switching ) 을 의미합니다.




프로세스 컨텍스트 스위칭 ( Process Context Switching ) 이란?

  • 서로 다른 프로세스 내부에 있는 쓰레드간의 컨텍스트 스위칭 ( Context Switching ) 을 의미합니다.




쓰레드 컨텍스트 스위칭 vs 프로세스 컨텍스트 스위칭 성능 차이

  • 프로세스마다 독립적인 주소 공간을 사용하기 때문에 다른 프로세스에 있는 쓰레드 간의 컨텍스트 스위칭이 발생될 경우 그전에 수행하던 쓰레드가 캐시TLB ( Translation Lookaside Buffer ) 에 적재하였던 데이터는 사용하지 못하기 때문에 캐시 hit율TLB ( Translation Lookaside Buffer ) hit율이 떨어져 프로세스 컨텍스트 스위칭보다는 쓰레드 컨텍스트 스위칭이 오버헤드가 상대적으로 적습니다.

 

 

네트워크 계층 구조란?

 

  • 네트워크 계층 구조란 네트워크 통신에 필요한 로직을 역학별로 구분하여 계층화된 구조를 말합니다.

 

  • 대표적인 네트워크 계층 모델로는 ISO(국제 표준화 기구) 에서 정의한 OSI 7계층과 TCP/IP 4계층이 있으며, 계층 구조의 차이는 있지만 서로 동일한 네트워크 프로토콜 표준을 따르고 있습니다.




네트워크 계층 구조가 필요한 이유

 

  • 네트워크 통신에 필요한 로직을 역할별로 계층화하고 특정 계층이 다른 계층에 영향을 주지 않도록 구분하여 네트워크 통신에서 과정에서 문제가 발생되었을 때 보다 쉽게 원인을 찾거나 해결할 수 있습니다.




OSI 7계층

 

7. 응용 계층 ( Application Layer )

 

  • 최종적으로 송.수신된 데이터를 이용해 응용 프로그램 사용자를 위한 로직을 수행합니다.




사용 가능 프로토콜

 

  • HTTP, FTP, SMTP, DNS 등이 있습니다.




패킷 이름

 

  • 응용 계층에서 생성된 데이터를 메시지라고 부릅니다.




6. 표현 계층 ( Presentation Layer )

 

  • 송.수신 데이터에 대한 인코딩, 디코딩을 담당합니다.




5. 세션 계층 ( Session Layer )

 

  • 세션 수립, 관리, 파기를 담당합니다.




4. 전송 계층 ( Transport Layer )

 

  • 포트를 이용하여 송.수신 대상이 되는 소켓을 특정할 수 있습니다.

 

  • TCP를 이용할 경우 안전한 송.수신이 가능합니다.




사용 가능 프로토콜

 

  • TCP, UDP




패킷 이름

 

세그먼트와 데이터그램의 패킷 구조

 

  • TCP는 세그먼트, UDP는 데이터그램으로 부릅니다.




네트워크 장비

 

  • L4 로드 밸런서




3. 네트워크 계층 ( Network Layer )

 

  • 논리적 주소인 IP 주소와 서브넷 마스크를 이용해서 목적지 호스트의 네트워크 ID를 식별하고 이를 통해 서로 다른 네트워크에 있는 호스트간에 통신을 담당합니다.




사용 가능 프로토콜

 

  • ARP, RARP, ICMP 등이 있습니다.




패킷 이름

 

IP 패킷

 

  • 네트워크 계층에서 생성된 패킷 이름을 IP 패킷으로 부릅니다.




네트워크 장비

 

  • L3 라우터




2. 데이터 링크 계층 ( Data Link Layer )

 

이더넷 프레임

 

  • 물리적 주소인 MAC 주소를 이용한 노드 대 노드 전송을 담당하며, 트레일러로 추가된 FCS(Frame Check Sequence) 을 통해 이더넷 프레임의 오류를 감지합니다.




패킷 이름

 

  • 데이터 링크 계층에서 생성된 패킷 이름을 이더넷 프레임 으로 부릅니다.




네트워크 장비

 

  • L2 스위치




1. 물리 계층 ( Physical Layer )

 

  • 전기 신호를 물리 신호로 또는 물리 신호를 전기 신호로 변환해주는 계층입니다.




TCP/IP 4계층

 

 

  • TCP/IP 4계층은 아래 사진과 같이 계층 구조의 차이가 있지만, 동일한 네트워크 프로토콜 표준을 따르고 있어 호환됩니다.




Interlocked 함수란?

  • Interlocked 계열의 함수들은 Interlocked 계열의 함수들 간의 원자적 연산을 보장해 주는 함수입니다.




Interlocked 함수의 원리

  • x86 아키텍처의 CPU라면 메모리 버스에 Interlocked 하드웨어 시그널을 실어서 다른 코어에서 해당 캐시 라인에 접근하지 못하도록 하여 Interlocked 함수를 이용한 원자적 연산을 지원합니다.




Interlocked 함수 사용 시 주의 사항

 

주의 사항 1

  • 캐시 라인 단위로 메모리 버스를 잠그기 때문에 Interlocked 계열의 함수에 사용될 변수들은 캐시 라인에 맞추어져 있어야 원자적 연산을 보장받습니다.




주의 사항 2

  • 멀티 쓰레드 환경에서 다른 목적으로 Interlocked 계열 함수에 사용될 변수들은 서로 다른 캐시 라인에 있어야 쓰레드 경합으로 인한 성능 저하가 발생되지 않습니다.




동일 캐시 라인에 대한 쓰레드 경합 테스트

 

테스트 방법

  • 동일한 캐시 라인에 있는 두 개의 변수들을 두 개의 쓰레드를 생성하여 각 쓰레드에서 InterlockedIncrement 를 천 만번 호출할때 소요되는 시간을 측정하여 비교합니다.




테스트 코드

#include <iostream>
#include <Windows.h>
#include <process.h>

#pragma comment(lib, "Winmm.lib")

HANDLE gEvent;

CRITICAL_SECTION gCS;

unsigned __stdcall TestThread(void* p)
{
    long* pNum = static_cast<long*>(p);

    if (WaitForSingleObject(gEvent, INFINITE) != WAIT_OBJECT_0)
    {
        std::cout << "Wait Failed\n";

        return 1;
    }

    LARGE_INTEGER start;
    LARGE_INTEGER end;
    LARGE_INTEGER frequency;
    QueryPerformanceFrequency(&frequency);

    QueryPerformanceCounter(&start);

    for (int i = 0; i < 10000000; ++i)
    {
        InterlockedIncrement(pNum);
    }

    QueryPerformanceCounter(&end);

    EnterCriticalSection(&gCS);

    std::cout << (double)(end.QuadPart - start.QuadPart) / frequency.QuadPart << " 초" <<std::endl;

    LeaveCriticalSection(&gCS);

    return 0;
}

int main()
{
    timeBeginPeriod(1);

    // 64Byte 경계에 맞춤
    __declspec(align(64))
    long num1, num2;

    std::cout << "num1 주소 : " << &num1 << std::endl;
    std::cout << "num2 주소 : " << &num2 << std::endl;

    HANDLE handles[2];

    InitializeCriticalSection(&gCS);

    gEvent = CreateEvent(nullptr, true, false, nullptr);

    handles[0] = (HANDLE)_beginthreadex(nullptr, 0, (_beginthreadex_proc_type)TestThread, &num1, 0, nullptr);
    handles[1] = (HANDLE)_beginthreadex(nullptr, 0, (_beginthreadex_proc_type)TestThread, &num2, 0, nullptr);

    Sleep(2000);

    SetEvent(gEvent);

    if (WaitForMultipleObjects(2, handles, true, INFINITE) != WAIT_OBJECT_0)
    {
        std::cout << "Handles Wait Failed\n";
    }

    timeEndPeriod(1);

    return 1;
}
  • 위와 같이 코드를 작성하여 각 쓰레드에서 InterlockedIncrement 테스트를 진행 하였습니다.




테스트 결과 비교

num1과 num2는 동일 캐시라인 선상

 

num1과 num2는 다른 캐시라인 선상

 

  • 테스트 결과 약 3.5배 정도 차이 나는 것을 확인하였지만, 성능 차이 정도는 쓰레드의 개수 및 하드웨어 환경에 따라 결과는 달라질 수 있습니다.




Interlocked 계열 함수들

 

InterlockedIncrement

  • 인자로 전달된 변수를 원자적으로 1 증가시키고 return 값은 증가시킨 값입니다.




InterlockedDecrement

  • 인자로 전달된 변수를 원자적으로 1 감소시키고 return 값은 감소시킨 값입니다.




InterlockedExchange

  • 원자적으로 첫 번째 인자의 값을 두 번째 인자의 값으로 변경하고 return 값은 첫 번째 인자의 변경 전 값입니다.




InterlockedCompareExchange ( CAS )

  • 원자적으로 첫 번째 인자의 포인터가 가리키는 값과 세 번째 값을 비교하여 동일하면 첫 번째 인자가 가리키는 값을 두 번째 인자의 값으로 치환합니다. return 값은 기존에 첫 번째 인자의 포인터가 가리키는 값입니다.


  • InterlockedCompareExchange 는 Compare And Swap 으로도 불립니다.



동기화 객체란?

  • 여러 쓰레드가 동시에 접근할 수 있는 영역에 쓰레드의 접근 순서를 맞추기 위해 사용하는 객체를 말합니다.
  • 동기화 객체는 크게 유저 모드 동기화 객체, 커널 모드 동기화 객체 가 있습니다.




동기화 객체를 사용하는 이유

  • 여러 쓰레드에서 접근할 수 있는 영역의 데이터를 특정 쓰레드가 변경하고 있을 때 다른 쓰레드가 접근하여 동일한 데이터를 읽거나 쓰기를 하여 의도하지 않은 결과가 발생될 수 있기 때문입니다.




유저 모드 동기화 객체의 특징 및 종류

유저 모드 동기화 객체의 특징

  • 자원에 대한 접근이 가능한지 여부를 유저 모드 상태에서 확인합니다.
  • CriticalSection, SRWLock 은 스핀 락의 일부 기능을 응용하여 스핀 카운트 만큼 루프를 돌면서 자원에 대한 접근이 가능한지 여부를 확인합니다.
  • 스핀 카운트를 모두 소모하고 자원에 대한 접근이 불가능할 경우 커널 모드로 전환되어 접근이 가능해질 때까지 블락됩니다.




유저 모드 동기화 객체의 종류

  • 유저 모드 동기화 객체의 종류로는 CriticalSection, SRWLock 이 있습니다.




CriticalSection

  • 배타적인 접근만을 허용합니다.
  • 중복락이 가능합니다.




SRWLock

  • Read, Write 락을 구분하여 사용할 수 있습니다.
  • 중복락이 불가능합니다.




커널 모드 동기화 객체의 특징 및 종류


커널 모드 동기화 객체의 특징

  • 자원에 대한 접근이 가능한지 여부 조차도 커널 모드로 전환하여 확인합니다.
  • 커널 모드 객체이기 때문에 다른 프로세스에 있는 쓰레드간에 동기화에도 사용될 수 있습니다.
  • 커널 모드의 시그널 상태 여부를 확인하여 동기화를 할 수 있습니다.
  • WaitForSingleObject, WaitForMultipleObject 등을 통해 커널 오브젝트의 시그널을 확인합니다.




커널 모드 동기화 객체의 종류

  • 커널 모드 동기화 객체의 종류로는 Mutex, Semaphore, Event 등이 있습니다.




Mutex

  • 배타적인 접근만을 허용합니다.
  • 중복락이 가능합니다.




Semaphore

  • 한 번에 접근할 수 있는 쓰레드의 개수를 지정할 수 있습니다.




Event

  • Event 는 Manual 또는 Auto 여부에 따라서 작동 방식이 달라지는 커널 모드 동기화 객체입니다.
  • Manual Event는 넌 시그널 상태에서 시그널 상태로 전환되었을 때 해당 Event의 시그널을 대기하고 있던 모든 쓰레드들을 깨우고 현재의 시그널 상태를 유지합니다.
  • Auto Event는 넌 시그널 상태에서 시그널 상태로 전환되었을 때 해당 Event의 시그널을 대기하고 있던 쓰레드들 중 하나를 깨우고 자동으로 넌 시그널 상태로 전환됩니다.

C++ 캐스트를 사용해야 하는 이유

  • 코드만 보고 캐스트를 사용한 목적을 확실히 알 수 있습니다.
  • 일부 캐스트는 컴파일 단계에서 에러를 확인할 수 있습니다.




C++ 캐스팅의 종류 및 사용방법

const_cast

  • const, volatile 특성을 제거할 때 사용하는 캐스트입니다.




dynamic_cast

  • 상속관계에 있는 사용자 정의 데이터 타입간에 업 캐스팅할 때 사용합니다.
  • 가상 함수를 가진 상속관계에 타입간에 캐스팅시에는 다운 캐스팅도 가능합니다.
  • 다운 캐스팅시 실제로 상속관계에 있는 타입인지 런 타임에 RTTI를 통해 검사하기 때문에 안전성 측면에서는 이점이 있지만, 검사하는 코드로 인해 성능상 좋지 못한 캐스트입니다.




reinterpret_cast

  • 어떠한 타입이든 캐스팅이 가능합니다.
  • 강력한 캐스트이지만, 컴파일러마다 캐스팅 결과가 다르기 때문에 이식성이 좋지 못합니다.




static_cast

  • 일반 데이터 타입간에 캐스팅을 허용합니다.
  • 일반 데이터 타입을 void*로 캐스팅이 가능합니다.
  • 상속관계에 있는 사용자 정의 데이터 타입간의 업, 다운 캐스팅이 가능합니다.

스핀 락 ( Spin Lock ) 이란?

  • 자신의 퀀텀타임을 포기하지 않고 무한 루프를 통해 자원에 대한 배타적인 접근을 시도하는 방식의 락을 말한다.




스핀 락 ( Spin Lock ) 코드

bool isUse = false;

// 접근 시도
while ((bool)InterlockedExchange8((char*)&isUse, false) == true)
{
    YieldProcessor();
}

// 대입은 원자적으로 이루어지기 때문에 Interlocked 함수를 사용하지 않는다.
isUse = false;
  • InterlockedExchange() 함수를 이용해서 원자적으로 isUse 의 값을 확인하면서 true로 값을 셋팅하여 무한 루프를 통해 배타적인 접근을 시도한다.




YieldProcessor() vs SwitchToThread() vs Sleep(0)

  • 배타적인 접근에 실패하였을 때 YieldProcessor(), SwitchToThread(), Sleep(0) 중 하나를 호출하여 다른 쓰레드가 실행될 수 있는 기회를 줄 수 있다.

YieldProcessor()

  • 하이퍼 쓰레드를 지원하는 CPU를 사용하는 머신에서 YieldProcessor()를 호출하였을 때, YieldProcessor()를 호출한 쓰레드가 실행되고 있는 물리 코어에 속해있는 논리 코어에게 실행을 양보한다.




SwitchToThread()

  • SwitchToThread()를 호출하였을 때 우선순위가 낮아 일정시간 동안 퀀텀 타임을 할당받지 못한 쓰레드에게 수행될 기회를 제공한다.




Sleep(0)

  • Sleep(0) 을 호출하였을 때 현재 퀀텀 타임을 포기하고 블락 큐에 인큐되지만, 자신 보다 우선순위가 같거나 높은 쓰레드가 없다면은 운영체제에 의해서 다시 퀀텀 타임을 할당받아 수행된다.




스핀 락 ( Spin Lock )의 장.단점

장점

  • 자신의 퀀텀 타임 이내에 배타적인 접근에 성공하였다면, 동기화 객체를 사용함으로서 발생될 수 있는 커널 모드로의 전환 및 컨택스트 스위칭으로 발생되는 오버헤드를 줄여 그만큼 성능에서 이점을 얻을 수 있다.




단점

  • 자신의 퀀텀 타임 이내에 배타적인 접근에 실패하였다면, 다른 쓰레드가 운영체제로부터 퀀텀 타임을 할당받아 수행될 수 있는 기회를 주지 못했기 때문에 전체적인 쓰레드 처리량이 떨어진다.

+ Recent posts