Это большой вопрос.
Во-первых, C ++ 98 / C ++ 03 не имеет понятия «поток». Так что в том мире вопрос бессмысленный.
А как насчет C ++ 0x? См . Ответ Мартиньо (который, признаюсь, меня удивил).
Как насчет конкретных реализаций до C ++ 0x? Ну, например, вот исходный код для basic_streambuf<...>:sputc
GCC 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
. И это определенно тот тип streambuf, который использует cout.
Насколько я могу судить, libstdc ++ не блокирует ни одну из потоковых операций. И я бы не ожидал, что это будет медленно.
Таким образом, с этой реализацией очевидно, что выход двух потоков может повредить друг друга (а не только чередоваться).
Может ли этот код повредить саму структуру данных? Ответ зависит от возможных взаимодействий этих функций; например, что произойдет, если один поток пытается очистить буфер, а другой пытается вызвать xsputn
или что-то еще. Это может зависеть от того, как ваш компилятор и процессор решат переупорядочить загрузку и хранение памяти; для уверенности потребуется тщательный анализ. Это также зависит от того, что делает ваш процессор, если два потока одновременно пытаются изменить одно и то же местоположение.
Другими словами, даже если он нормально работает в вашей текущей среде, он может выйти из строя, когда вы обновите любую среду выполнения, компилятор или процессор.
Резюме: «Я бы не стал». Создайте класс ведения журнала, который выполняет правильную блокировку, или перейдите на C ++ 0x.
В качестве слабой альтернативы вы можете установить для cout значение без буферизации. Вероятно (хотя и не гарантируется), что вся логика, связанная с буфером, будет пропущена и будет выполняться write
прямой вызов . Хотя это может быть слишком медленно.