Synchronization Demo
#include <iostream> #include <cstdlib> #include <list> #include <thread> #include <mutex> using namespace std; // This is a global counter. int global_counter = 0; // This is a thread which simply increments the global counter a bunch of // times without locking it. That's a bad idea. void bad_incrementer(int num) { while(num--) ++global_counter; } // This is a mutex to synchronize increments on the global counter so it can // be incremented correctly. mutex counter_lock; // This increments the global counter the indicated number of times, but // locks the mutex each time so the increment will be correct. void good_incrementer(int num) { while(num--) { counter_lock.lock(); ++global_counter; counter_lock.unlock(); } } // Get an integer from the command line, with default int getint(int &argc, char ** &argv, int dflt) { if(argc > 0) { dflt = atoi(argv[0]); --argc; ++argv; } return dflt; } // This main program is run with parameters [ protect ] nthread and niter, // which will start nthread threads running, each making niter iterations, // wait them, then see how many increments were lost. If the protect word // is given, the threads will synchronize increments, otherwise they don't. int main(int argc, char **argv) { // Get rid of program name. --argc; ++argv; // Collect the arguments. bool protect = false; if(argc > 0 && argv[0] == string("protect")) { protect = true; --argc; ++argv; } int nthread = getint(argc, argv, 10); int niter = getint(argc, argv, 10); // Create the threads. list<thread> threads; for(int n = 0; n < nthread; ++n) { if(protect) threads.push_back(thread(good_incrementer, niter)); else threads.push_back(thread(bad_incrementer, niter)); } // Join the threads. for(thread &t: threads) t.join(); // Report the results. int nincr = nthread*niter; cout << "Global counter is " << global_counter << ", was incremented " << nincr << " times. "; if(global_counter < nincr) cout << nincr - global_counter << " lost increments (" << 100.0*(nincr - global_counter)/nincr << "%." << endl; else cout << "No lost increments." << endl; }