c++ - GCC 4.7.2 on Debian amd64 - built-in atomic increment? -
my test source is:
volatile int gl = 0; void * internalhandler( void * param ) { ( int = 0; < 100000; ++i ) { ++gl; } return 0; } int main() { pthread_t ths[100] = { 0 }; ( int = 0; < 100; ++i) { pthread_create( &ths[ ], 0, internalhandler, 0 ); } ( int = 0; < 100; ++i) { pthread_join( ths[ ], 0 ); } std::cout << gl << std::endl; return 0; }
when compile , run code on debian (via virtualbox), 10000000 every time, while has race condition.
uname -a:
linux debian-dev 3.2.0-4-amd64 #1 smp debian 3.2.46-1 x86_64 gnu/linux
gcc -v:
using built-in specs. collect_gcc=gcc collect_lto_wrapper=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper target: x86_64-linux-gnu configured with: ../src/configure -v --with-pkgversion='debian 4.7.2-5' --with-bugurl=file:///usr/share/doc/gcc-4.7/readme.bugs --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu thread model: posix gcc version 4.7.2 (debian 4.7.2-5)
on several other systems different results. race conditions job. on virtual debian it's "implicit atomic". why be?
there data race.
you don't see because virtual machine using single core; , running on architecture performs increment using single cpu instruction (meaning task switch can't happen in middle of it).
if run on multi-core machine, or architecture (such arm) doesn't have cpu instructions directly modifying values in memory, should see inconsistent results expected.
for example, if run on 8-core machine get:
$ ./a.out 1666121 $ ./a.out 1632606
while constraining single core gives
$ taskset -c 0 ./a.out 10000000 $ taskset -c 0 ./a.out 10000000
you can fix data race using std::atomic<int>
. if c++11 not available, use platform-specific atomic operations such gcc's __sync_fetch_and_add
, or (if performance impact acceptable) guard variable mutex.
Comments
Post a Comment