
For what I've seen in code, read_write_mutex has a lot of options regarding reader/writer priorities and for that uses conditions and mutexes to offer that functionality. The overhead is bigger than mutexes, but I think the critical section you have chosen is very small, and where read_writer_mutex shines is when you have to lock expensive operations (lookups for example, in data-bases) with lots of readers. In that case, a mutex would serialize all, but read_writer_mutex would allow concurrent readers. Ion ----- Original Message ----- From: "Peter Dimov" <pdimov@mmltd.net> To: "boost-devel" <boost@lists.boost.org> Sent: Sunday, April 24, 2005 3:07 PM Subject: [boost] [threads] read_write_mutex performance
What are the design goals of read_write_mutex? (Lock proliferation aside for a moment.)
My understanding has always been that read/write locks are an optimization, that is, a read/write lock-based algorithm should deliver better performance than the same algorithm with "ordinary" locks. Right?
Wrong.
The program at the end of this message demonstrates that in this specific (contrived?) case ordinary mutexes outperform a read/write mutex by a factor of 2.5 or more in almost every scenario, even when no writers are active!
In some scenarios (16 readers, 4 writers, 10,000,000 iterations) the ordinary mutex case completes in under 8 seconds on my machine, but the read/write case exceeded my patience threshold.
Am I missing something?
-- Peter Dimov http://www.pdimov.com
#include <boost/thread.hpp> #include <boost/thread/read_write_mutex.hpp> #include <iostream> #include <vector> #include <time.h>
//#define RWLOCK
int const n = 1000000; int const n_readers = 16; int const n_writers = 0;
std::vector<int> v;
#ifdef RWLOCK
boost::read_write_mutex mtx( boost::read_write_scheduling_policy::alternating_many_reads );
#else
boost::mutex mtx;
#endif
void reader_thread() { int m = 0;
for( int i = 0; i < n; ++i ) { #ifdef RWLOCK
boost::read_write_mutex::scoped_read_lock lock( mtx );
#else
boost::mutex::scoped_lock lock( mtx );
#endif
m += v[ i ]; }
std::cout << m << std::endl; }
void writer_thread() { for( int i = 0; i < n; ++i ) { #ifdef RWLOCK
boost::read_write_mutex::scoped_write_lock lock( mtx );
#else
boost::mutex::scoped_lock lock( mtx );
#endif
v[ i ] += i; } }
int main() { v.resize( n );
boost::thread_group group;
clock_t t = clock();
for( int i = 0; i < n_writers; ++i ) { group.add_thread( new boost::thread( writer_thread ) ); }
for( int i = 0; i < n_readers; ++i ) { group.add_thread( new boost::thread( reader_thread ) ); }
group.join_all();
t = clock() - t;
std::cout << static_cast<double>( t ) / CLOCKS_PER_SEC << '\n'; }