Just tested 3 thread synchronization methods on a multi-cpu machine:
# I'm using Boost v1.53 on Ubunt 12.04.01 LTS/amd64
# (download the package, run "./bootstrap.sh --prefix=$prefix; ./b2 -q -j4 install")
c++ -O3 -fPIC -std=c++0x -fpermissive -pthread -Wall -Wl,-rpath=$prefix/lib -I$prefix/include -o boost_threads_atomic_test_case.bin boost_threads_atomic_test_case.cpp -L$prefix/lib -lboost_unit_test_framework -lboost_filesystem -lboost_chrono -lboost_thread -lboost_system -lpthread -lrt
#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread.hpp>
#include <vector>
#include <iostream>
#include <atomic>
namespace {
// Shared variables for generation barrier test
const int N_THREADS = 10;
const long N_PER_THREAD = 10000000;
boost::mutex mutex;
std::atomic<long> global_parameter{0};
void barrier_thread() {
// boost::thread::id tid = boost::this_thread::get_id();
long todo = N_PER_THREAD;
while(todo > 0) {
// std::cout << tid << " lock(mutex)" << std::endl;
//boost::unique_lock<boost::mutex> lock(mutex);
// std::cout << global_parameter << " " << tid << " global_parameter++" << std::endl;
global_parameter++;
todo--;
}
}
} // namespace
BOOST_AUTO_TEST_CASE(test) {
boost::thread_group g;
global_parameter = 0;
try {
for (int i = 0; i < N_THREADS; ++i)
g.create_thread(&barrier_thread);
g.join_all();
} catch (...) {
g.interrupt_all();
g.join_all();
throw;
}
BOOST_CHECK_EQUAL(global_parameter, N_THREADS * N_PER_THREAD);
}
#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread.hpp>
#include <vector>
#include <iostream>
namespace {
// Shared variables for generation barrier test
const int N_THREADS = 10;
const long N_PER_THREAD = 1000000;
boost::mutex mutex;
volatile long global_parameter;
void barrier_thread() {
// boost::thread::id tid = boost::this_thread::get_id();
long todo = N_PER_THREAD;
while(todo > 0) {
// std::cout << tid << " lock(mutex)" << std::endl;
boost::unique_lock<boost::mutex> lock(mutex);
// std::cout << global_parameter << " " << tid << " global_parameter++" << std::endl;
global_parameter++;
todo--;
}
}
} // namespace
BOOST_AUTO_TEST_CASE(test) {
boost::thread_group g;
global_parameter = 0;
try {
for (int i = 0; i < N_THREADS; ++i)
g.create_thread(&barrier_thread);
g.join_all();
} catch (...) {
g.interrupt_all();
g.join_all();
throw;
}
BOOST_CHECK_EQUAL(global_parameter, N_THREADS * N_PER_THREAD);
}
/**
* Runs into a deadlock.
*/
#define BOOST_TEST_MODULE example
#include <boost/test/included/unit_test.hpp>
#define BOOST_THREAD_PROVIDES_INTERRUPTIONS
#include <boost/thread/detail/config.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/barrier.hpp>
#include <vector>
#include <iostream>
namespace {
// Shared variables for generation barrier test
const int N_THREADS = 10;
const long N_PER_THREAD = 100;
boost::barrier gen_barrier(N_THREADS);
boost::mutex mutex;
volatile long global_parameter;
void barrier_thread() {
boost::thread::id tid = boost::this_thread::get_id();
long todo = N_PER_THREAD;
while(todo > 0) {
std::cout << tid << " gen_barrier.wait()" << std::endl;
// this causes deadlocks...
if (gen_barrier.wait()) {
std::cout << tid << " lock(mutex)" << std::endl;
boost::unique_lock<boost::mutex> lock(mutex);
std::cout << global_parameter << " " << tid << " global_parameter++" << std::endl;
global_parameter++;
todo--;
}
}
}
} // namespace
BOOST_AUTO_TEST_CASE(test) {
boost::thread_group g;
global_parameter = 0;
std::cerr << "skipping this test case because it is deadlock prone" << std::endl;
return;
try {
for (int i = 0; i < N_THREADS; ++i)
g.create_thread(&barrier_thread);
g.join_all();
} catch (...) {
g.interrupt_all();
g.join_all();
throw;
}
BOOST_CHECK_EQUAL(global_parameter, N_THREADS * N_PER_THREAD);
}