I'm having trouble understanding how I should use std::mutex. Most examples I found use only one mutex and it's declared at global scope, and we all know that's bad practice right?
What I understood is: whenever I want to access a shared resource(s) I lock a mutex assigned to control that resource(s) so that other threads will be blocked until I unlock it. Is this right? If it is, pairing up a mutex and a resource is just a matter of me remembering which mutex I use for which resource?
#include <mutex>
struct shared_resource
{
// ...
void do_something()
{
// access to instance restricted to one thread at a time
std::lock_guard<std::mutex> lock( instance_lock ) ;
// access non-static members
// ...
// access to static members restricted to one thread at a time
{
std::lock_guard<std::mutex> lock( class_lock ) ;
// access static members
// ...
} // class_lock is released
// ...
} // instance_lock is released
private:
std::mutex instance_lock ; // std::recursive_mutex
static std::mutex class_lock ; // std::recursive_mutex
// non-staic members
// static members
};
For more complex resources, one could use a mutex to serialize access. The typical usage should be one mutex to control all access to one resource. A simple approach is to use one mutex to control access to an object (through all functions) ie. treat the complete object as a single resource.
> That means I can't directly use a member variable
> I need to write a getter and a setter for each one right?
Yes. Assuming that your class is a simple unencapsulated type.
And the getters need to return by value.
In this case, for performance reasons, you might want to implement a reader-writer lock.
boost has a shared_mutex and an upgradable shared_lock<>.
As does C++14: http://en.cppreference.com/w/cpp/thread/shared_mutex