※ ios_base::sync_with_stdio(bool sync);

bool sync == false: C 의 stdio.h와 C++의 iostream의 동기화를 끊는다.

bool sync == true: 함수 호출하기 전 이전의 동기화 상태

 

[sync : true]

- 모든 stream들은 동기화가 되어있으며 동기화된 stream들이 자신의 buffer대신 C stream buffer를 사용

stream buffer: data를 보내거나 받기 전, 임시로 저장되는 곳으로

바로 사용하지 않고 버퍼에서 보관, 어느정도 모이면 출력하는 방식으로 작업함.

 

- 동기화된 C++ stream들은 thread-safe, 안정성을 보장한다.

- 따라서 입출력 순서가 정해져있어서 race condition이 발생하지 않는다. (race condition: https://chan4im.tistory.com/36)

 

this->OS.code(5)

다수의 thread가 concurrent하게 실행 => thread 충돌문제 발생이 가능하다. cf. single thread의 경우, process 충돌이라고도 부른다. - race condition: 2개 이상의 process가 같은 메모리를 거의 동시에 접근(access)할

chan4im.tistory.com

 

[sync : false]

- 동기화를 끊게되면 C++ stream은 자신들의 독립적인 buffer를 갖게된다.

- 따라서 입출력 객체를 섞어 사용하면 출력순서를 보장할 수 없어 오답, race condition 발생 가능성이 있다.

- multi-thread의 경우, Thread-unsafe해져서 예상하지 못한 값이 나올 수도 있다.

 

※ 입출력 속도비교

[scanf, printf, \n]  >>>>>>>> [cin, cout, endl]

 

 

 

 

§  ios_base::sync_with_stdio() 함수

먼저 C++의 <iostream>은 C의 <stdio.h>와 다르다. 

C++의 입출력 작업 시, C의 입출력과 동기화 되도록 설계되어 상당히 느린 입출력과정을 겪는다.

추가적으로 endl도 출력문자 출력+출력buffer를 함께 비워 시간이 많이 걸려 \n사용을 권장한다.

이때 말하는 "동기화"를 뜻하는 코드가 ios_base::sync_with_stdio이고, 이 동기화를 풀어주는 코드이다.

따라서 동기화가 풀어진다면?  => 당연히 속도를 올릴 수 있다!

ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);

 

큰 힘에는 큰 책임이 따른다고, 이런 ios_base::sync_with_stdio에도 치명적인 단점이 있다.

 

1. 그건 바로 싱글 쓰레드 (single thread) 환경은 괜찮지만, 멀티 쓰레드 (Multi Thread)환경에서는 출력순서가 어그러진다.

즉, 멀티쓰레드 환경에서의 출력순서가 보장될 수 없다는 것이다! (race condition 발생 가능)

cf-1) 코딩테스트에서는 싱글쓰레드만 사용하기에 사용해도 무방하다.

cf-2) 다만 실무에서는 ios_base::sync_with_stdio를 쓰기보단, 속도를 올리기 위해 C입출력 방식을 권장한다.

 

 

2. 버퍼가 분리되었기에 cin과 scanf, gets, getchar 등의 C문법 (당연히 출력코드도 동일)을 같이 사용할 수 없다!

 

cf-2) 싱글, 멀티쓰레드란? https://chan4im.tistory.com/35

 

this->OS.code(4)

exit() system call, 처리불가능한 signal, CPU err, 부모 process의 명령과 같은 상황에서 process termination이 발생하며 아직 process 상태에 존재한다. (process에 존재하지만 실행에 필요한 컴퓨터 자원들을 proces

chan4im.tistory.com

 

 

 

§  cin.tie(NULL)  /  cout.tie(NULL) 함수

[정의]: istream, ostream 즉, stream을 untie 하여 자동으로 입출력 버퍼를 비우지 않게 함

cin과 cout간의 tie를 끊어주는, 즉 다른 입출력이 온다면 기존의 입출력을 비워주도록 하는 것이다.

이 tie를 끊어줌으로써 시간을 많이 절감할 수 있다. (cin을 cout으로부터 풀어줌.)

기본적으로 cout의 출력은 buffer가 가득차거나 수동적으로 flush되기 전까진 출력되지 않는다.

 

[flush]: 현재 buffer에 저장되있는 내용클라이언트로 전송buffer를 비우는 것을 말함.

 

- stream을 tie하면 다른 stream에서 입출력 요청이 오기 전stream을 먼저 flush 시킨다.

 

- stream을 untie하면 output이 flush되지 않은 채로 user에게 input을 요구한다.

- untie를 해주었다면, cin으로 입력받기 전, 출력하고 싶다면 수동적으로 cout을 flush 해줘야 한다.

 

[예시]

왼쪽그림에서 ios_base::sync_with_stdio(0);을 지워도 console창은 하게 뜬다.

왼쪽을 보면 cout으로 "입력"이란 문구가 출력된 후 cin이 나오는 것을 알 수 있고, 이는 익숙한 방식이다.

하지만 우측은 입력 후 출력이 모두 동시에 되는 것을 알 수 있다.

우리가 tie를 끊어서 입력 전에 출력관련 문구가 아무리 입력보다 먼저 적혀있었더라도 출력이 되지 않는다.

만약 입력전에 출력되게 하고 싶다면 cout의  buffer를 수동으로 비워줘야 한다.

+ Recent posts