Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a getter function need a mutex?

I have a class that is accessed from multiple threads. Both of its getter and setter functions are guarded with locks.

Are the locks for the getter functions really needed? If so, why?

class foo {
public:
    void setCount (int count) {
        boost::lock_guard<boost::mutex> lg(mutex_);
        count_ = count;
    }

    int count () {
        boost::lock_guard<boost::mutex> lg(mutex_); // mutex needed?
        return count_;
    }

private:
    boost::mutex mutex_;
    int count_;
};
like image 988
cairol Avatar asked Feb 12 '10 14:02

cairol


3 Answers

The only way you can get around having the lock is if you can convince yourself that the system will transfer the guarded variable atomicly in all cases. If you can't be sure of that for one reason or another, then you'll need the mutex.

For a simple type like an int, you may be able to convince yourself this is true, depending on architecture, and assuming that it's properly aligned for single-instruction transfer. For any type that's more complicated than this, you're going to have to have the lock.

like image 81
Michael Kohne Avatar answered Nov 20 '22 05:11

Michael Kohne


If you don't have a mutex around the getter, and a thread is reading it while another thread is writing it, you'll get funny results.

like image 6
Joseph Salisbury Avatar answered Nov 20 '22 06:11

Joseph Salisbury


Is the mutex really only protecting a single int? It makes a difference -- if it is a more complex datatype you definitely need locking.

But if it is just an int, and you are sure that int is an atomic type (i.e., the processor will not have to do two separate memory reads to load the int into a register), and you have benchmarked the performance and determined you need better performance, then you may consider dropping the lock from both the getter and the setter. If you do that, make sure to qualify the int as volatile. And write a comment explaining why you do not have mutex protection, and under what conditions you would need it if the class changes.

Also, beware that you don't have code like this:

void func(foo &f) {
  int temp = f.count();
  ++temp;
  f.setCount(temp);
}

That is not threadsafe, regardless of whether you use a mutex or not. If you need to do something like that, the mutex protection has to be outside the setter/getter functions.

like image 4
Dan Avatar answered Nov 20 '22 06:11

Dan