머리 쓰레드로 인한 동기화 문제를 고려하지 않고 개발할 수 있어서 생산성 및 유지 보수성에 이점이 있습니다.
멀티 쓰레드 환경에서 동기화로 인해 발생되는 잦은 커널 모드 전환 및 컨택스트 스위칭 비용을 아낄 수 있습니다.
단점
멀티 코어 CPU를 활용하기에 적합하지 못합니다.
사용자에 대한 응답을 하나의 쓰레드로 처리하기 때문에 응답성이 떨어집니다.
여러 개의 작업을 하나의 쓰레드로 일렬로 처리할 수밖에 없습니다.
멀티 쓰레드 장.단점
장점
멀티 코어 CPU를 적극 활용할 수 있습니다.
멀티 쓰레드로 여러 개의 작업을 처리할 수 있기 때문에 병렬성을 극대화할 수 있습니다.
Accept, Send, Recv를 담당하는 쓰레드를 만들어서 설계를 단순화할 수 있습니다.
사용자 응답을 위한 별도의 쓰레드를 만들어서 사용자에게 보다 빠르게 응답할 수 있습니다.
단점
멀티 쓰레드 간의 동기화 작업으로 인한 경합이 자주 발생될 경우 오히려 성능이 떨어질 수 있습니다.
프로그래머가 멀티 쓰레드 환경을 고려하며 코딩해야 하기 때문에 컨텐츠 생산성 및 유지 보수성이 떨어질 수 있습니다.
쓰레드가 처리하는 작업량보다 컨텍스트 스위칭 비용이 더 클 경우 멀티 쓰레드를 사용함으로써의 이점이 없습니다.
싱글, 멀티 쓰레드 결론
무조건 멀티 쓰레드가 좋다고 생각하진 않습니다. 성능의 중요성이 떨어지는 프로젝트라면 되도록 싱글 쓰레드로 개발하여 생산성 및 유지보수성을 증가 시키는 것도 좋은 방법이라 생각됩니다.
하지만, 사용자 응답성 및 성능을 중요시 한다면 싱글 쓰레드는 적합하지 못하다고 생각합니다. 그리고 멀티 쓰레드 설계를 통해 Accept, Send, Recv 로직을 담당하는 쓰레드를 별도로 둠으로써 오히려 구조적 단순화의 이점을 얻을 수 있기 때문에 여러가지 상황을 고려한 쓰레드 설계가 필요하다 생각합니다.
자신의 퀀텀타임을 포기하지 않고 무한 루프를 통해 자원에 대한 배타적인 접근을 시도하는 방식의 락을 말한다.
스핀 락 ( 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 )의 장.단점
장점
자신의 퀀텀 타임 이내에 배타적인 접근에 성공하였다면, 동기화 객체를 사용함으로서 발생될 수 있는 커널 모드로의 전환 및 컨택스트 스위칭으로 발생되는 오버헤드를 줄여 그만큼 성능에서 이점을 얻을 수 있다.
단점
자신의 퀀텀 타임 이내에 배타적인 접근에 실패하였다면, 다른 쓰레드가 운영체제로부터 퀀텀 타임을 할당받아 수행될 수 있는 기회를 주지 못했기 때문에 전체적인 쓰레드 처리량이 떨어진다.