i find strange phenomenon when using global variable parameter in c++. here code. program never end if using -o2.
#include <thread> #include <iostream> using namespace std; #define nthreads 2 struct global{ int a[nthreads]; }; void func(int* a){ while(*a == 0){ } cout << "done" << endl; } struct global global; int main(){ thread pid[nthreads]; memset(global.a, 0, nthreads*sizeof(int)); for(int i=0; i<nthreads; i++){ pid[i] = std::thread(func, &global.a[i]); } sleep(2); cout << "finished" << endl; memset(global.a, 1, nthreads*sizeof(int)); for(int i=0; i<nthreads; i++){ pid[i].join(); } return 0; }
if using -o0, seems ok. , print variable *a in while loop, still ok.
so guess must problem of c++ optimization. how compiler make such aggressive optimization global variable , multi-thread?
thanks answers , comments, tried use volatile , work. don't want use mutex because using mutex in every loop influence performance.
in fact, want this:
a worker thread loops through global list , execution in each while loop.(i don't want use mutex here, because not matter though mistake happens in 1 loop)
some other threads possibly add items list.(mutex used here ok. because each thread adds 1 time)
what should correctly?
the current code allows compiler optimize if there's no threading. , when compiler sees loop unchanging condition, can optimize away. or, seems behavior observed, replace intended memory fetch in condition value register.
one way make work use std::atomic
.
i've dabbled in multithreading in modern c++, purposes of learning , exploration, code's working:
#include <atomic> #include <array> #include <thread> #include <iostream> using namespace std; int const nthreads = 2; void func( atomic<int>* ) { while( a->load() == 0 ) {} cout << "done" << endl; } namespace global { array<atomic<int>, nthreads> a; // zero-initialized automatically. } // namespace global auto main() -> int { using namespace std::chrono_literals; thread pid[nthreads]; for( int = 0; < nthreads; ++i ) { pid[i] = thread( func, &global::a[i] ); } this_thread::sleep_for( 2ms ); cout << "finished" << endl; for( auto& item : global::a ) { item = ( int( unsigned( -1 ) & 0x0101010101010101 ) ); } for( int = 0; < nthreads; ++i) { pid[i].join(); } }
Comments
Post a Comment