multithreading - How to forbid C++ compiler optimizing when using global variable as parameters -


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:

  1. 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)

  2. 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