boost::lock_guard vs. boost::mutex::scoped_lock

Among the many different locks available in boost, boost::lock_guard is the simplest one.

What we can do with a lock_guard is just acquiring ownership of a mutex (actually, a Lockable) when constructing it and waiting its exiting of scope to have the mutex released by the destructor.

The scoped_lock, actually a typedef for unique_lock, is a more complex concept. A couple of useful functions available for this class are lock()/unlock() that allow to have a better control on locking.

The basic behavior provided by lock_guard suffices for large part of the cases, so it is better to stick to it as default, and use scoped_lock - or even some other more powerful lock - when we have complex requirements.

As example of lock_guard usage I rewrite a short test from a previous post, where originally a scoped_lock was used (even though it was not necessary):
#include <iostream>
#include "boost/thread/thread.hpp"
#include "boost/thread/locks.hpp"

using std::cout;
using std::endl;

namespace
{
   boost::mutex mio;

   class Count
   {
   private:
      int multi_;
   public:
      Count(int multi) : multi_(multi) { }

      void operator()()
      {
         for(int i = 0; i < 5; ++i)
         {
            boost::lock_guard<boost::mutex> lock(mio);
            std::cout << "Thread " << boost::this_thread::get_id() << " is looping: " << i*multi_ << std::endl;
            boost::this_thread::sleep(boost::posix_time::milliseconds(10));
         }
      }
   };
}

void t05()
{
   std::cout << "Main thread " << boost::this_thread::get_id() << std::endl; 
   boost::thread t1(Count(1));
   {
      boost::lock_guard<boost::mutex> lock(mio);
      std::cout << "Thread 1 started" << std::endl;
   }

   boost::thread t2(Count(-1));
   {
      boost::lock_guard<boost::mutex> lock(mio);
      std::cout << "Thread 2 started" << std::endl;
   }

   boost::thread t3(Count(10));
   {
      boost::lock_guard<boost::mutex> lock(mio);
      std::cout << "Thread 3 started" << std::endl;
   }

   t1.join();
   t2.join();
   t3.join();
   std::cout << "Back to the main thread " << std::endl;
}

No comments:

Post a Comment