cout은 동기화 / 스레드 안전합니까?
일반적으로 스트림이 동기화되지 않았다고 가정하면 적절한 잠금을 수행하는 것은 사용자의 책임입니다. 그러나 cout표준 라이브러리에서 특별한 대우를받는 것과 같은 것들이 있습니까?
즉, 여러 스레드가 쓰면 객체 cout를 손상시킬 수 cout있습니까? 동기화 되더라도 여전히 무작위로 인터리브 된 출력을 얻지 만 인터리빙은 보장된다는 것을 알고 있습니다. 즉, cout여러 스레드에서 사용하는 것이 안전 합니까?
이 공급 업체는 의존적입니까? gcc는 무엇을합니까?
중요 : 이에 대한 증거가 필요하기 때문에 "예"라고 답한 경우 답변을 참조하십시오.
내 관심사는 기본 시스템 호출에 관한 것이 아니라 괜찮지 만 스트림은 버퍼링 레이어를 추가하는 것입니다.
C ++ 03 표준은 그것에 대해 아무 말도하지 않습니다. 스레드 안전에 대해 보장 할 수없는 경우 스레드 안전이 아닌 것으로 취급해야합니다.
cout버퍼링 되는 사실이 특히 중요합니다 . 호출이 write(또는 특정 구현에서 그 효과를 달성하는 것이 무엇이든) 상호 배타적임을 보장하더라도 다른 스레드가 버퍼를 공유 할 수 있습니다. 이것은 스트림의 내부 상태를 빠르게 손상시킵니다.
그리고 버퍼에 대한 액세스가 스레드로부터 안전하다고 보장 되더라도이 코드에서 어떤 일이 일어날 것이라고 생각하십니까?
// in one thread
cout << "The operation took " << result << " seconds.";
// in another thread
cout << "Hello world! Hello " << name << "!";
여기의 각 줄이 상호 배제로 작동하기를 원할 것입니다. 그러나 구현이 어떻게이를 보장 할 수 있습니까?
C ++ 11에서는 몇 가지 보장이 있습니다. FDIS는 §27.4.1 [iostream.objects.overview]에서 다음과 같이 말합니다.
여러 스레드에 의해 동기화 된 (§27.5.3.4) 표준 iostream 객체의 형식화 및 형식화되지 않은 입력 (§27.7.2.1) 및 출력 (§27.7.3.1) 기능 또는 표준 C 스트림에 대한 동시 액세스는 데이터 경쟁을 초래하지 않아야합니다 (§ 1.10). [참고 : 인터리브 된 문자를 피하려면 사용자는 여전히 이러한 객체와 스트림의 동시 사용을 여러 스레드에서 동기화해야합니다. — 끝 참고]
따라서 손상된 스트림은 발생하지 않지만 출력이 가비지 않게하려면 수동으로 동기화해야합니다.
이것은 좋은 질문입니다.
먼저 C ++ 98 / C ++ 03에는 "스레드"라는 개념이 없습니다. 그래서 그 세계에서 질문은 의미가 없습니다.
C ++ 0x는 어떻습니까? Martinho의 답변을 참조하십시오 (놀랐습니다).
C ++ 0x 이전의 특정 구현은 어떻습니까? 예를 들어 basic_streambuf<...>:sputcGCC 4.5.2 ( "streambuf"헤더) 의 소스 코드는 다음과 같습니다.
int_type
sputc(char_type __c)
{
int_type __ret;
if (__builtin_expect(this->pptr() < this->epptr(), true)) {
*this->pptr() = __c;
this->pbump(1);
__ret = traits_type::to_int_type(__c);
}
else
__ret = this->overflow(traits_type::to_int_type(__c));
return __ret;
}
분명히 이것은 잠금을 수행하지 않습니다. 그리고 둘 다 xsputn. 그리고 이것은 cout이 사용하는 streambuf의 유형입니다.
내가 알 수있는 한 libstdc ++는 스트림 작업을 잠그지 않습니다. 그리고 나는 느릴 것으로 예상하지 않습니다.
따라서이 구현을 통해 분명히 두 개의 스레드 출력이 인터리브가 아닌 서로를 손상시킬 수 있습니다.
Could this code corrupt the data structure itself? The answer depends on the possible interactions of these functions; e.g., what happens if one thread tries to flush the buffer while another tries to call xsputn or whatever. It might depend on how your compiler and CPU decide to reorder memory loads and stores; it would take a careful analysis to be sure. It also depends what your CPU does if two threads try to modify the same location concurrently.
In other words, even if it happens to work fine in your current environment, it might break when you update any of your runtime, compiler, or CPU.
Executive summary: "I wouldn't". Build a logging class that does proper locking, or move to C++0x.
As a weak alternative, you could set cout to unbuffered. It is likely (although not guaranteed) that would skip all logic related to the buffer and call write directly. Although that might be prohibitively slow.
The C++ Standard does not specify whether writing to streams is thread-safe, but usually it's not.
www.techrepublic.com/article/use-stl-streams-for-easy-c-plus-plus-thread-safe-logging
and also: Are standard output streams in C++ thread-safe (cout, cerr, clog)?
UPDATE
Please have a look at @Martinho Fernandes' answer to know about what the new standard C++11 tells about this.
As other answers mention, this is definitely vendor-specific since the C++ standard makes no mention of threading (this changes in C++0x).
GCC doesn't make a whole lot of promises about thread safety and I/O. But the documentation for what it does promise is here:
the key stuff is probably:
The __basic_file type is simply a collection of small wrappers around the C stdio layer (again, see the link under Structure). We do no locking ourselves, but simply pass through to calls to fopen, fwrite, and so forth.
So, for 3.0, the question of "is multithreading safe for I/O" must be answered with, "is your platform's C library threadsafe for I/O?" Some are by default, some are not; many offer multiple implementations of the C library with varying tradeoffs of threadsafety and efficiency. You, the programmer, are always required to take care with multiple threads.
(As an example, the POSIX standard requires that C stdio FILE* operations are atomic. POSIX-conforming C libraries (e.g, on Solaris and GNU/Linux) have an internal mutex to serialize operations on FILE*s. However, you still need to not do stupid things like calling fclose(fs) in one thread followed by an access of fs in another.)
So, if your platform's C library is threadsafe, then your fstream I/O operations will be threadsafe at the lowest level. For higher-level operations, such as manipulating the data contained in the stream formatting classes (e.g., setting up callbacks inside an std::ofstream), you need to guard such accesses like any other critical shared resource.
I don't know if anything has changed sine the 3.0 timeframe mentioned.
MSVC's thread safety documentation for iostreams can be found here: http://msdn.microsoft.com/en-us/library/c9ceah3b.aspx:
A single object is thread safe for reading from multiple threads. For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously.
If a single object is being written to by one thread, then all reads and writes to that object on the same or other threads must be protected. For example, given an object A, if thread 1 is writing to A, then thread 2 must be prevented from reading from or writing to A.
It is safe to read and write to one instance of a type even if another thread is reading or writing to a different instance of the same type. For example, given objects A and B of the same type, it is safe if A is being written in thread 1 and B is being read in thread 2.
...
iostream Classes
The iostream classes follow the same rules as the other classes, with one exception. It is safe to write to an object from multiple threads. For example, thread 1 can write to cout at the same time as thread 2. However, this can result in the output from the two threads being intermixed.
Note: Reading from a stream buffer is not considered to be a read operation. It should be considered as a write operation, because this changes the state of the class.
Note that that information is for the most recent version of MSVC (currently for VS 2010/MSVC 10/cl.exe 16.x). You can select the information for older versions of MSVC using a dropdown control on the page (and the information is different for older versions).
참고URL : https://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe
'Programing' 카테고리의 다른 글
| ASP.NET MVC가 빈보기를 반환합니다. (0) | 2020.08.07 |
|---|---|
| C ++에서 함수의 실행 시간 측정 (0) | 2020.08.07 |
| 멀티 프로세싱의 공유 메모리 개체 (0) | 2020.08.06 |
| 멀티 모듈 메이븐 프로젝트에서 모듈 간 src / test 클래스 공유 (0) | 2020.08.06 |
| JavaScript를위한 간단한 (비보안) 해시 함수? (0) | 2020.08.06 |