#include <iostream>
#include <sstream>
#include <thread>
using namespace std;
int main()
{
auto runner = []() {
ostringstream oss;
for (int i=0; i<100000; ++i)
oss << i;
};
thread t1(runner), t2(runner);
t1.join(); t2.join();
}
用g ++ 6.2.1編譯上面的代碼,然後用valgrind --tool=helgrind ./a.out
運行它。 Helgrind會抱怨:運算符<<(ostream&,obj)在兩個不同的線程上是否安全?
==5541== ----------------------------------------------------------------
==5541==
==5541== Possible data race during read of size 1 at 0x51C30B9 by thread #3
==5541== Locks held: none
==5541== at 0x4F500CB: widen (locale_facets.h:875)
==5541== by 0x4F500CB: widen (basic_ios.h:450)
==5541== by 0x4F500CB: fill (basic_ios.h:374)
==5541== by 0x4F500CB: std::ostream& std::ostream::_M_insert<long>(long) (ostream.tcc:73)
==5541== by 0x400CD0: main::{lambda()#1}::operator()() const (43.cpp:12)
==5541== by 0x4011F7: void std::_Bind_simple<main::{lambda()#1}()>::_M_invoke<>(std::_Index_tuple<>) (functional:1391)
==5541== by 0x401194: std::_Bind_simple<main::{lambda()#1}()>::operator()() (functional:1380)
==5541== by 0x401173: std::thread::_State_impl<std::_Bind_simple<main::{lambda()#1}()> >::_M_run() (thread:197)
==5541== by 0x4EF858E: execute_native_thread_routine (thread.cc:83)
==5541== by 0x4C31A04: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5541== by 0x56E7453: start_thread (in /usr/lib/libpthread-2.24.so)
==5541== by 0x59E57DE: clone (in /usr/lib/libc-2.24.so)
==5541==
==5541== This conflicts with a previous write of size 8 by thread #2
==5541== Locks held: none
==5541== at 0x4EF3B1F: do_widen (locale_facets.h:1107)
==5541== by 0x4EF3B1F: std::ctype<char>::_M_widen_init() const (ctype.cc:94)
==5541== by 0x4F501B7: widen (locale_facets.h:876)
==5541== by 0x4F501B7: widen (basic_ios.h:450)
==5541== by 0x4F501B7: fill (basic_ios.h:374)
==5541== by 0x4F501B7: std::ostream& std::ostream::_M_insert<long>(long) (ostream.tcc:73)
==5541== by 0x400CD0: main::{lambda()#1}::operator()() const (43.cpp:12)
==5541== by 0x4011F7: void std::_Bind_simple<main::{lambda()#1}()>::_M_invoke<>(std::_Index_tuple<>) (functional:1391)
==5541== by 0x401194: std::_Bind_simple<main::{lambda()#1}()>::operator()() (functional:1380)
==5541== by 0x401173: std::thread::_State_impl<std::_Bind_simple<main::{lambda()#1}()> >::_M_run() (thread:197)
==5541== by 0x4EF858E: execute_native_thread_routine (thread.cc:83)
==5541== by 0x4C31A04: ??? (in /usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so)
==5541== Address 0x51c30b9 is 89 bytes inside data symbol "_ZN12_GLOBAL__N_17ctype_cE"
看來,這兩個線程調用locale_facet.h:widen
造成數據競爭,因爲有出現在該函數沒有同步,即使operator <<
被稱爲在兩個不同的ostringstream
對象。所以我想知道這是真的是數據競賽還是隻是一個誤報helgrind
。
不管是什麼標準說,這應該* *是線程安全的。 –
標準狀態*多線程併發訪問流對象(27.8,27.9),流緩衝對象(27.6)或C庫流(27.9.2) 可能會導致數據競爭(1.10),除非另有說明( 27.4)。 [注意:數據競賽 導致未定義的行爲(1.10)。 - 結束註釋] *所以我的猜測是流在後端使用了一些不同步的全局狀態。或者這是一個誤報。我的直覺說這應該是安全的。 – NathanOliver
我認爲這應該是安全的根據§17.6.5.9/ 2:*「C++標準庫函數不應直接或間接訪問除當前線程之外的線程可訪問的對象(1.10),除非通過直接或間接訪問對象函數的參數,包括'this'。「*所以我會說這是一個不符合的實現或者是一個誤報。 –