상세 컨텐츠

본문 제목

Thread를 실행할 때 std::cout와 printf의 출력이 다른 이유

카테고리 없음

by state 2023. 7. 18. 21:40

본문

 std::cout는 C++의 표준 출력 버퍼로 기본적으로 버퍼링이 되어 있습니다. 버퍼링은 출력 작업의 효율성을 높이는데 사용됩니다. 작은 양의 출력이 쌓여도 버퍼가 가득 차지 않는다면 출력이 지연될 수 있지는 말입니다.

 반면에 printf는 C언어의 표준 라이브러리 함수입니다. 버퍼링이 뭔지 모르는 아이로 문자열을 출력할 때 마다 바로 출력장치로 전송됩니다. 그리하여 빈번하게 호출을 할 때 출력이 지연되지 않고 출력할 수 있습니다.

 따라서 여러 개의 스레드가 동시에 std::cout로 출력한다면 개별 스레드의 출력 내용이 버퍼링되어 뒤섞인 상태로 출력될 수도 있습니다. 이를 race condition이라고 하며 스레드 간의 출력 순서와 결과를 일관되게 관리하기 위해서 동기화 기법* 을 사용하거나 상호 배제**를 하여야 합니다.

 

 버퍼링은 데이터를 일시적으로 저장하는 임시 메모리 영역에서의 작업으로 효율성과 성능 개선을 위하여 사용됩니다. 출력 버퍼는 전송 받은 데이터를 일정량만큼 모았다가 한번에 출력하거나 특정 조건이 충족되기까지 기다립니다. 이는 적은 양의 출력을 반복적으로 수행하는데 걸리는 비용을 줄이기 위함입니다. ( 출력 장치와의 통신 횟수가 감소하고 입출력 오버헤드*** 도 감소합니다 )

 입력작업에서도 사용되며 데이터를 한번에 읽어서 버퍼에 저장한 다음 필요할 때 버퍼에서 읽어들이는 방식으로 사용합니다.

 

* 동기화 기법 (Synchronization)은 락 (Lock)과 조건 변수(Conditional Variable) 등을 사용합니다. 락은 임계 구역 (Critical Section)을 보호하여 한번에 하나의 스레드만 접근할 수 있도록 합니다. 조건 변수는 스레드의 대기와 신호 전달을 제어하며 특정 조건을 충족할 때 까지 스레드를 대기시키거나 실행합니다.

 

** 상호 배제 (Mutal Exclusion)은 여러 스레드가 공유 자원에 동시에 접근하지 못하도록 하며 락과 뮤텍스 (Mutex)를 사용합니다. 이들은 한번에 하나의 스레드만 자원에 접근할 수 있도록 하며 자원에 접근하는 스레드는 락을 획득하고 작업이 완료되면 락을 해제합니다. std::mutex, std::lock_guard, std::condition_variable 클래스를 사용합니다.

 

*** 오버헤드는 작업을 수행하기 위해서 추가적으로 발생하는 비용 및 부담을 의미합니다. 추가적인 시간을 소요시키는 시간적 오버헤드 / 메모리 자원을 낭비시키는 공간적 오버헤드 / 시스템 리소스를 낭비하는 리소스 오버헤드 / 작업의 복잡성 ( 코드 분기 및 알고리즘의 복잡성) 을 증기시키는 복잡성 오버헤드가 존재합니다. 최적화된 알고리즘과 데이터 구조, 자원 관리 및 병렬 처리의 균형 등을 고려하여 오버헤드를 최소화하는 것이 중요합니다.

댓글 영역