/* * simple synchronization example, version 2: * * synchronize access to a resource (here, standard output) using mutex * (lock), another way. * * command-line argument gives number of threads. */ #include #include #include #include #include void thread_fcn(int thread_id, int num_threads, std::mutex& print_lock); /* ---- main program ---- */ int main(int argc, char* argv[]) { const char* usage_fmt = "usage: %s number_of_threads\n"; /* process command-line arguments */ char* end_ptr_for_strtol; if (argc != 2) { fprintf(stderr, usage_fmt, argv[0]); exit(EXIT_FAILURE); } int num_threads = strtol(argv[1], &end_ptr_for_strtol, 10); if (*end_ptr_for_strtol != '\0') { fprintf(stderr, usage_fmt, argv[0]); exit(EXIT_FAILURE); } std::cout << "hello from main program\n"; std::vector threads; std::mutex print_lock; /* create and start threads */ for (int i = 0; i < num_threads; ++i) { /* * note use of std::ref: * apparently this is needed to pass something by reference to * the function for a thread to execute */ threads.push_back(std::thread(thread_fcn, i, num_threads, std::ref(print_lock))); } { std::unique_lock lock(print_lock); std::cout << "threads launched\n"; /* * no need to explicitly release lock -- released when unique_lock * goes out of scope */ } /* wait for threads to finish */ for (auto& t : threads) { t.join(); } std::cout << "threads all done\n"; return EXIT_SUCCESS; } /* ---- code to be executed by each thread ---- */ void thread_fcn(int thread_id, int num_threads, std::mutex& print_lock) { std::unique_lock lock(print_lock); std::cout << "hello from thread " << thread_id << " of " << num_threads << "\n"; /* * no need to explicitly release lock -- released when unique_lock * goes out of scope */ }