Hi.
There is a test program I would to be explained to me:
*** BEGIN OF TEST PROGRAM ***
#include
inlined below:
On Thu, Jan 28, 2010 at 12:23 PM, Andrew Chinkoff
Hi.
There is a test program I would to be explained to me:
*** BEGIN OF TEST PROGRAM *** #include
#include
//> #define USE_SPINLOCKS #define USE_ATOMICS (you are using atomics, not spinlocks)
//#define USE_MUTEXES
boost::thread th1; boost::thread th2;
boost::mutex mutex;
int global_int = 0;
// put the mutex and/or atomics inside this function, // where it is really needed - protecting you global data - instead of in your for loop int read_global_int() {
#ifdef USE_MUTEXES boost::mutex::scoped_lock locker(mutex); return global_int;
#elif USE_ATOMICS // add 0 to global_int. Seems odd, but by doing this with atomic __sync functions // we guarantee proper memory ordering and visibility, as well as atomicity return __sync_fetch_and_add(&global_int, 0);
#else ERROR__WRONG_COMPILED; #endif
} //> bool IsNotEven(int code) // better name: bool IsOdd(int code)
{ // no longer grab mutex here. This is now a useful function for *any* integer return !!(code & 1); // using !! to convert to bool }
void thread_func() { for(int i = 0; i < 1000000; ++i) { // mutex/atomic handling is inside read_global_int() if(IsOdd(read_global_int())) global_int+=9; // what about mutex/atomic here? else global_int+=1; // and here? } }
int main() { th1 = boost::thread(&thread_func); th2 = boost::thread(&thread_func); th1.join(); th2.join(); printf("global_int = %d\n", global_int);
return 0; } *** END OF TEST PROGRAM ***
Results of test program:
1) Test program compiled with USE_SPINLOCKS. Outputs are always: "global_int = 10" "global_int = 10" "global_int = 10"
2) Test program compiled with USE_MUTEXES. Outputs differ from each other: "global_int = 10000008" "global_int = 10000000" "global_int = 9763210"
Could you explain me why outputs produced with USE_SPINLOCKS compilation differ from USE_MUTEXES ones? And what is the difference between (1) and (2) lines?
So now they should both look like (2). In order to get a consistent result (global_int = 10000000), you need to replace your global_int += 9 and += 1 with __sync instructions. ie increase_global_int(int inc) { // TO DO // do this atomically or with locks: // global_int += inc; }
Best, Andrew.
Tony
participants (2)
-
Andrew Chinkoff
-
Gottlob Frege