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